bosh_vsphere_cpi 2.2.0 → 2.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -17,7 +17,7 @@ module VSphereCloud
17
17
  end
18
18
 
19
19
  attr_accessor :client
20
- attr_reader :datacenter
20
+ attr_reader :config, :datacenter
21
21
 
22
22
  def initialize(options)
23
23
  @config = Config.build(options)
@@ -39,7 +39,6 @@ module VSphereCloud
39
39
  mem_overcommit: @config.mem_overcommit
40
40
  })
41
41
 
42
- @resources = Resources.new(@datacenter, config)
43
42
  @file_provider = FileProvider.new(config.rest_client, config.vcenter_host)
44
43
  @agent_env = AgentEnv.new(client, @file_provider, @cloud_searcher)
45
44
 
@@ -67,7 +66,7 @@ module VSphereCloud
67
66
  end
68
67
 
69
68
  def has_disk?(disk_cid)
70
- disk_provider.find(disk_cid)
69
+ @datacenter.find_disk(disk_cid)
71
70
  true
72
71
  rescue Bosh::Clouds::DiskNotFound
73
72
  false
@@ -89,8 +88,12 @@ module VSphereCloud
89
88
  @logger.info("Generated name: #{name}")
90
89
 
91
90
  stemcell_size = File.size(image) / (1024 * 1024)
92
- cluster = @resources.pick_cluster_for_vm(0, stemcell_size, [])
93
- datastore = @resources.pick_ephemeral_datastore(cluster, stemcell_size)
91
+
92
+ cluster = @datacenter.pick_cluster_for_vm(0, stemcell_size, [])
93
+ if cluster.ephemeral_datastores.empty?
94
+ raise "Cluster '#{cluster.name}' has no ephemeral datastores"
95
+ end
96
+ datastore = @datacenter.pick_ephemeral_datastore(stemcell_size, cluster.ephemeral_datastores.keys)
94
97
  @logger.info("Deploying to: #{cluster.mob} / #{datastore.mob}")
95
98
 
96
99
  import_spec_result = import_ovf(name, ovf_file, cluster.resource_pool.mob, datastore.mob)
@@ -113,7 +116,7 @@ module VSphereCloud
113
116
 
114
117
  nics = devices.select { |device| device.kind_of?(Vim::Vm::Device::VirtualEthernetCard) }
115
118
  nics.each do |nic|
116
- nic_config = create_delete_device_spec(nic)
119
+ nic_config = Resources::VM.create_delete_device_spec(nic)
117
120
  config.device_change << nic_config
118
121
  end
119
122
  client.reconfig_vm(vm, config)
@@ -155,8 +158,20 @@ module VSphereCloud
155
158
 
156
159
  def create_vm(agent_id, stemcell, cloud_properties, networks, disk_locality = nil, environment = nil)
157
160
  with_thread_name("create_vm(#{agent_id}, ...)") do
161
+ datacenter_spec = cloud_properties.fetch('datacenters', []).first
162
+ cluster_spec = datacenter_spec.fetch('clusters', []).first if datacenter_spec
163
+
164
+ drs_rules = []
165
+ cluster = nil
166
+ unless cluster_spec.nil?
167
+ cluster_name = cluster_spec.keys.first
168
+ spec = cluster_spec.values.first
169
+ cluster_config = ClusterConfig.new(cluster_name, spec)
170
+ cluster = Resources::ClusterProvider.new(@datacenter, @client, @logger).find(cluster_name, cluster_config)
171
+ drs_rules = spec.fetch('drs_rules', [])
172
+ end
173
+
158
174
  VmCreatorBuilder.new.build(
159
- choose_placer(cloud_properties),
160
175
  cloud_properties,
161
176
  @client,
162
177
  @cloud_searcher,
@@ -164,7 +179,9 @@ module VSphereCloud
164
179
  self,
165
180
  @agent_env,
166
181
  @file_provider,
167
- disk_provider
182
+ @datacenter,
183
+ cluster,
184
+ drs_rules
168
185
  ).create(agent_id, stemcell, networks, disk_locality, environment)
169
186
  end
170
187
  end
@@ -178,15 +195,7 @@ module VSphereCloud
178
195
 
179
196
  persistent_disks = vm.persistent_disks
180
197
  unless persistent_disks.empty?
181
- @logger.info("Found #{persistent_disks.size} persistent disk(s)")
182
- config = Vim::Vm::ConfigSpec.new
183
- config.device_change = []
184
- persistent_disks.each do |virtual_disk|
185
- @logger.info("Detaching: #{virtual_disk.backing.file_name}")
186
- config.device_change << create_delete_device_spec(virtual_disk)
187
- end
188
- retry_block { client.reconfig_vm(vm.mob, config) }
189
- @logger.info("Detached #{persistent_disks.size} persistent disk(s)")
198
+ vm.detach_disks(persistent_disks)
190
199
  end
191
200
 
192
201
  # Delete env.iso and VM specific files managed by the director
@@ -247,6 +256,8 @@ module VSphereCloud
247
256
  if e.fault.kind_of?(Vim::Fault::NoPermission)
248
257
  @logger.warn("Can't set custom fields due to lack of " +
249
258
  "permission: #{e.message}")
259
+ elsif e.fault.kind_of?(Vim::Fault::DuplicateName)
260
+ @logger.warn("Can't add custom field definition that already exists: #{e.message}")
250
261
  else
251
262
  raise e
252
263
  end
@@ -263,7 +274,7 @@ module VSphereCloud
263
274
  config = Vim::Vm::ConfigSpec.new
264
275
  config.device_change = []
265
276
  vm.nics.each do |nic|
266
- nic_config = create_delete_device_spec(nic)
277
+ nic_config = Resources::VM.create_delete_device_spec(nic)
267
278
  config.device_change << nic_config
268
279
  end
269
280
 
@@ -271,7 +282,9 @@ module VSphereCloud
271
282
  networks.each_value do |network|
272
283
  v_network_name = network['cloud_properties']['name']
273
284
  network_mob = client.find_by_inventory_path([@datacenter.name, 'network', v_network_name])
274
- nic_config = create_nic_config_spec(v_network_name, network_mob, vm.pci_controller.key, dvs_index)
285
+
286
+ virtual_nic = Resources::Nic.create_virtual_nic(@cloud_searcher, v_network_name, network_mob, vm.pci_controller.key, dvs_index)
287
+ nic_config = Resources::VM.create_add_device_spec(virtual_nic)
275
288
  config.device_change << nic_config
276
289
  end
277
290
 
@@ -301,72 +314,24 @@ module VSphereCloud
301
314
  def attach_disk(vm_cid, disk_cid)
302
315
  with_thread_name("attach_disk(#{vm_cid}, #{disk_cid})") do
303
316
  @logger.info("Attaching disk: #{disk_cid} on vm: #{vm_cid}")
304
-
305
317
  vm = vm_provider.find(vm_cid)
306
- cluster = @datacenter.clusters[vm.cluster]
307
-
308
- disk = disk_provider.find_and_move(disk_cid, cluster, @datacenter, vm.accessible_datastores)
309
- disk_config_spec = disk.attach_spec(vm.system_disk.controller_key)
310
-
311
- vm_config = Vim::Vm::ConfigSpec.new
312
- vm_config.device_change = []
313
- vm_config.device_change << disk_config_spec
314
- vm.fix_device_unit_numbers(vm_config.device_change)
315
-
316
- env = @agent_env.get_current_env(vm.mob, @datacenter.name)
317
- @logger.info("Reading current agent env: #{env.pretty_inspect}")
318
- env['disks']['persistent'][disk_cid] = disk_config_spec.device.unit_number.to_s
319
- @logger.info("Updating agent env to: #{env.pretty_inspect}")
320
-
321
- location = get_vm_location(vm.mob, datacenter: @datacenter.name)
322
- @agent_env.set_env(vm.mob, location, env)
323
- @logger.info('Attaching disk')
324
- client.reconfig_vm(vm.mob, vm_config)
325
- @logger.info('Finished attaching disk')
318
+ disk = @datacenter.find_disk(disk_cid)
319
+ disk = @datacenter.ensure_disk_is_accessible_to_vm(disk, vm)
320
+ disk_config_spec = vm.attach_disk(disk)
321
+ add_disk_to_agent_env(vm, disk, disk_config_spec.device.unit_number)
326
322
  end
327
323
  end
328
324
 
329
325
  def detach_disk(vm_cid, disk_cid)
330
326
  with_thread_name("detach_disk(#{vm_cid}, #{disk_cid})") do
331
327
  @logger.info("Detaching disk: #{disk_cid} from vm: #{vm_cid}")
332
- disk = disk_provider.find(disk_cid)
333
- vm = vm_provider.find(vm_cid)
334
- vm_mob = vm.mob
335
-
336
- location = get_vm_location(vm_mob)
337
- env = @agent_env.get_current_env(vm_mob, location[:datacenter])
338
- @logger.info("Reading current agent env: #{env.pretty_inspect}")
339
- if env['disks']['persistent'][disk.cid]
340
- env['disks']['persistent'].delete(disk.cid)
341
- @logger.info("Updating agent env to: #{env.pretty_inspect}")
342
-
343
- @agent_env.set_env(vm_mob, location, env)
344
- end
345
-
346
- vm.reload
347
- virtual_disk = vm.disk_by_cid(disk.cid)
348
- raise Bosh::Clouds::DiskNotAttached.new(true), "Disk '#{disk.cid}' is not attached to VM '#{vm.cid}'" if virtual_disk.nil?
349
328
 
350
- config = Vim::Vm::ConfigSpec.new
351
- config.device_change = []
352
- config.device_change << create_delete_device_spec(virtual_disk)
353
-
354
- @logger.info('Detaching disk')
355
- client.reconfig_vm(vm_mob, config)
356
-
357
- # detach-disk is async and task completion does not necessarily mean
358
- # that changes have been applied to VC side. Query VC until we confirm
359
- # that the change has been applied. This is a known issue for vsphere 4.
360
- # Fixed in vsphere 5.
361
- 5.times do
362
- vm.reload
363
- virtual_disk = vm.disk_by_cid(disk.cid)
364
- break if virtual_disk.nil?
365
- sleep(1.0)
366
- end
367
- raise "Failed to detach disk '#{disk.cid}' from vm '#{vm.cid}'" unless virtual_disk.nil?
329
+ vm = vm_provider.find(vm_cid)
330
+ disk = vm.disk_by_original_cid(disk_cid)
331
+ raise Bosh::Clouds::DiskNotAttached.new(true), "Disk '#{disk_cid}' is not attached to VM '#{vm_cid}'" if disk.nil?
368
332
 
369
- @logger.info('Finished detaching disk')
333
+ delete_disk_from_agent_env(vm, disk_cid)
334
+ vm.detach_disks([disk])
370
335
  end
371
336
  end
372
337
 
@@ -374,15 +339,17 @@ module VSphereCloud
374
339
  with_thread_name("create_disk(#{size_in_mb}, _)") do
375
340
  @logger.info("Creating disk with size: #{size_in_mb}")
376
341
 
377
- cluster = nil
342
+ filtered_datastores = []
378
343
  if vm_cid
379
344
  vm = vm_provider.find(vm_cid)
380
- cluster = @datacenter.clusters[vm.cluster]
345
+ filtered_datastores = vm.accessible_datastores
381
346
  end
382
347
 
383
- disk_type = cloud_properties['type']
384
- disk = disk_provider.create(size_in_mb, disk_type, cluster)
348
+ datastore = @datacenter.pick_persistent_datastore(size_in_mb, filtered_datastores)
349
+ disk_type = cloud_properties.fetch('type', Resources::PersistentDisk::DEFAULT_DISK_TYPE)
350
+ disk = @datacenter.create_disk(datastore, size_in_mb, disk_type)
385
351
  @logger.info("Created disk: #{disk.inspect}")
352
+
386
353
  disk.cid
387
354
  end
388
355
  end
@@ -390,39 +357,82 @@ module VSphereCloud
390
357
  def delete_disk(disk_cid)
391
358
  with_thread_name("delete_disk(#{disk_cid})") do
392
359
  @logger.info("Deleting disk: #{disk_cid}")
393
- disk = disk_provider.find(disk_cid)
360
+ disk = @datacenter.find_disk(disk_cid)
394
361
  client.delete_disk(@datacenter.mob, disk.path)
395
362
 
396
363
  @logger.info('Finished deleting disk')
397
364
  end
398
365
  end
399
366
 
400
- def replicate_stemcell(cluster, datastore, stemcell)
401
- stemcell_vm = client.find_vm_by_name(@datacenter, stemcell)
402
- raise "Could not find VM for stemcell '#{stemcell}'" if stemcell_vm.nil?
403
- stemcell_datastore = @cloud_searcher.get_property(stemcell_vm, Vim::VirtualMachine, 'datastore', ensure_all: true)
367
+ def replicate_stemcell(cluster, to_datastore, stemcell_id)
368
+ original_stemcell_vm = self.client.find_vm_by_name(@datacenter, stemcell_id)
369
+ raise "Could not find VM for stemcell '#{stemcell_id}'" if original_stemcell_vm.nil?
370
+
371
+ return original_stemcell_vm if vm_datastore_name(original_stemcell_vm) == to_datastore.name
372
+
373
+ @logger.info("Stemcell lives on a different datastore, looking for a local copy of: #{stemcell_id}.")
374
+
375
+ name_of_replicated_stemcell = "#{stemcell_id} %2f #{to_datastore.mob.__mo_id__}"
376
+
377
+ replicated_stemcell_vm = client.find_vm_by_name(@datacenter, name_of_replicated_stemcell)
378
+ return replicated_stemcell_vm if replicated_stemcell_vm
379
+
380
+ @logger.info("Cluster doesn't have stemcell #{stemcell_id}, replicating")
381
+ @logger.info("Replicating #{stemcell_id} (#{original_stemcell_vm}) to #{name_of_replicated_stemcell}")
382
+ begin
383
+ replicated_stemcell_vm = client.wait_for_task(clone_vm(
384
+ original_stemcell_vm,
385
+ name_of_replicated_stemcell,
386
+ cluster.datacenter.template_folder.mob,
387
+ cluster.resource_pool.mob,
388
+ datastore: to_datastore.mob
389
+ ))
390
+ @logger.info("Replicated #{stemcell_id} (#{original_stemcell_vm}) to #{name_of_replicated_stemcell} (#{replicated_stemcell_vm})")
391
+
392
+ @logger.info("Creating initial snapshot for linked clones on #{replicated_stemcell_vm}")
393
+ client.wait_for_task(replicated_stemcell_vm.create_snapshot('initial', nil, false, false))
394
+ @logger.info("Created initial snapshot for linked clones on #{replicated_stemcell_vm}")
395
+ rescue VSphereCloud::Client::DuplicateName
396
+ @logger.info("Stemcell is being replicated by another thread, waiting for #{name_of_replicated_stemcell} to be ready")
397
+ replicated_stemcell_vm = client.find_by_inventory_path([
398
+ cluster.datacenter.name,
399
+ 'vm',
400
+ cluster.datacenter.template_folder.path_components,
401
+ name_of_replicated_stemcell
402
+ ])
403
+ # get_properties will ensure the existence of the snapshot by retrying.
404
+ # This forces us to wait for a valid snapshot before returning with the
405
+ # replicated stemcell vm, if a snapshot is not found then an exception is thrown.
406
+ client.cloud_searcher.get_properties(replicated_stemcell_vm,
407
+ VimSdk::Vim::VirtualMachine,
408
+ ['snapshot'], ensure_all: true)
409
+ @logger.info("Stemcell #{name_of_replicated_stemcell} has been replicated.")
410
+ end
411
+
412
+ replicated_stemcell_vm
413
+ end
414
+
404
415
 
405
- if stemcell_datastore != datastore.mob
406
- @logger.info("Stemcell lives on a different datastore, looking for a local copy of: #{stemcell}.")
407
- local_stemcell_name = "#{stemcell} %2f #{datastore.mob.__mo_id__}"
416
+ def vm_datastore_name(vm)
417
+ vm_datacenters = @cloud_searcher.get_property(
418
+ vm,
419
+ Vim::VirtualMachine,
420
+ 'datastore',
421
+ ensure_all: true
422
+ )
408
423
 
409
- replicated_stemcell_vm = client.find_vm_by_name(@datacenter, local_stemcell_name)
410
- if replicated_stemcell_vm.nil?
411
- @logger.info("Cluster doesn't have stemcell #{stemcell}, replicating")
412
- replicated_stemcell_vm = replicate_stemcell_helper(stemcell, stemcell_vm, local_stemcell_name, cluster, datastore, replicated_stemcell_vm)
413
- else
414
- @logger.info("Found local stemcell replica: #{replicated_stemcell_vm}")
415
- end
416
- result = replicated_stemcell_vm
417
- else
418
- @logger.info("Stemcell was already local: #{stemcell_vm}")
419
- result = stemcell_vm
424
+ if vm_datacenters.size > 1
425
+ raise "stemcell VM #{vm.inspect} found in multiple datacenters #{datacenters.inspect}"
420
426
  end
421
- @logger.info("Using stemcell VM: #{result}")
422
427
 
423
- result
428
+ if vm_datacenters.size == 0
429
+ raise "no datacenter found for stemcell VM #{vm.inspect}"
430
+ end
431
+
432
+ vm_datacenters.first.name
424
433
  end
425
434
 
435
+
426
436
  def generate_network_env(devices, networks, dvs_index)
427
437
  nics = {}
428
438
 
@@ -533,52 +543,6 @@ module VSphereCloud
533
543
  vm.clone(folder, name, clone_spec)
534
544
  end
535
545
 
536
- def create_nic_config_spec(v_network_name, network, controller_key, dvs_index)
537
- raise "Invalid network '#{v_network_name}'" if network.nil?
538
- if network.class == Vim::Dvs::DistributedVirtualPortgroup
539
- portgroup_properties = @cloud_searcher.get_properties(network,
540
- Vim::Dvs::DistributedVirtualPortgroup,
541
- ['config.key', 'config.distributedVirtualSwitch'],
542
- ensure_all: true)
543
-
544
- switch = portgroup_properties['config.distributedVirtualSwitch']
545
- switch_uuid = @cloud_searcher.get_property(switch, Vim::DistributedVirtualSwitch, 'uuid', ensure_all: true)
546
-
547
- port = Vim::Dvs::PortConnection.new
548
- port.switch_uuid = switch_uuid
549
- port.portgroup_key = portgroup_properties['config.key']
550
-
551
- backing_info = Vim::Vm::Device::VirtualEthernetCard::DistributedVirtualPortBackingInfo.new
552
- backing_info.port = port
553
-
554
- dvs_index[port.portgroup_key] = v_network_name
555
- else
556
- backing_info = Vim::Vm::Device::VirtualEthernetCard::NetworkBackingInfo.new
557
- backing_info.device_name = network.name
558
- backing_info.network = network
559
- end
560
-
561
- nic = Vim::Vm::Device::VirtualVmxnet3.new
562
- nic.key = -1
563
- nic.controller_key = controller_key
564
- nic.backing = backing_info
565
-
566
- device_config_spec = Vim::Vm::Device::VirtualDeviceSpec.new
567
- device_config_spec.device = nic
568
- device_config_spec.operation = Vim::Vm::Device::VirtualDeviceSpec::Operation::ADD
569
- device_config_spec
570
- end
571
-
572
- def create_delete_device_spec(device, options = {})
573
- device_config_spec = Vim::Vm::Device::VirtualDeviceSpec.new
574
- device_config_spec.device = device
575
- device_config_spec.operation = Vim::Vm::Device::VirtualDeviceSpec::Operation::REMOVE
576
- if options[:destroy]
577
- device_config_spec.file_operation = Vim::Vm::Device::VirtualDeviceSpec::FileOperation::DESTROY
578
- end
579
- device_config_spec
580
- end
581
-
582
546
  def import_ovf(name, ovf, resource_pool, datastore)
583
547
  import_spec_params = Vim::OvfManager::CreateImportSpecParams.new
584
548
  import_spec_params.entity_name = name
@@ -672,71 +636,28 @@ module VSphereCloud
672
636
  )
673
637
  end
674
638
 
675
- def disk_provider
676
- DiskProvider.new(
677
- @client.service_content.virtual_disk_manager,
678
- @datacenter,
679
- @resources,
680
- @config.datacenter_disk_path,
681
- @client,
682
- @logger
683
- )
684
- end
685
-
686
639
  private
687
640
 
688
- def choose_placer(cloud_properties)
689
- datacenter_spec = cloud_properties.fetch('datacenters', []).first
690
- cluster_spec = datacenter_spec.fetch('clusters', []).first if datacenter_spec
691
-
692
- unless cluster_spec.nil?
693
- cluster_name = cluster_spec.keys.first
694
- spec = cluster_spec.values.first
695
- cluster_config = ClusterConfig.new(cluster_name, spec)
696
- cluster = Resources::ClusterProvider.new(@datacenter, @client, @logger).find(cluster_name, cluster_config)
697
- drs_rules = spec.fetch('drs_rules', [])
698
- placer = FixedClusterPlacer.new(cluster, drs_rules)
699
- end
700
-
701
- placer.nil? ? @resources : placer
702
- end
703
-
704
- def replicate_stemcell_helper(stemcell, stemcell_vm, local_stemcell_name, cluster, datastore, replicated_stemcell_vm)
705
- @logger.info("Replicating #{stemcell} (#{stemcell_vm}) to #{local_stemcell_name}")
706
- task = clone_vm(stemcell_vm,
707
- local_stemcell_name,
708
- cluster.datacenter.template_folder.mob,
709
- cluster.resource_pool.mob,
710
- datastore: datastore.mob)
711
- begin
712
- replicated_stemcell_vm = client.wait_for_task(task)
713
- @logger.info("Replicated #{stemcell} (#{stemcell_vm}) to #{local_stemcell_name} (#{replicated_stemcell_vm})")
714
- rescue VSphereCloud::Client::DuplicateName => ex
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]
718
- replicated_stemcell_vm = client.find_by_inventory_path(local_stemcell_path)
719
- # get_properties will ensure the existence of the snapshot by retrying.
720
- # This forces us to wait for a valid snapshot before returning with the
721
- # replicated stemcell vm, if a snapshot is not found then an exception is thrown.
722
- client.cloud_searcher.get_properties(replicated_stemcell_vm,
723
- VimSdk::Vim::VirtualMachine,
724
- ['snapshot'], ensure_all: true)
725
- @logger.info("Stemcell #{local_stemcell_name} has been replicated.")
726
-
727
- return replicated_stemcell_vm
728
- end
729
- # Despite the naming, this has nothing to do with the Cloud notion of a disk snapshot
730
- # (which comes from AWS). This is a vm snapshot.
731
- @logger.info("Creating initial snapshot for linked clones on #{replicated_stemcell_vm}")
732
- task = replicated_stemcell_vm.create_snapshot('initial', nil, false, false)
733
- client.wait_for_task(task)
734
- @logger.info("Created initial snapshot for linked clones on #{replicated_stemcell_vm}")
735
-
736
- replicated_stemcell_vm
737
- end
738
-
739
- attr_reader :config
641
+ def add_disk_to_agent_env(vm, disk, device_unit_number)
642
+ env = @agent_env.get_current_env(vm.mob, @datacenter.name)
643
+ @logger.info("Reading current agent env: #{env.pretty_inspect}")
644
+ env['disks']['persistent'][disk.cid] = device_unit_number.to_s
645
+ location = get_vm_location(vm.mob, datacenter: @datacenter.name)
646
+ @agent_env.set_env(vm.mob, location, env)
647
+ @logger.info("Updated agent env to: #{env.pretty_inspect}")
648
+ end
649
+
650
+ def delete_disk_from_agent_env(vm, disk_cid)
651
+ vm_mob = vm.mob
652
+ location = get_vm_location(vm_mob)
653
+ env = @agent_env.get_current_env(vm_mob, location[:datacenter])
654
+ @logger.info("Reading current agent env: #{env.pretty_inspect}")
655
+ if env['disks']['persistent'][disk_cid]
656
+ env['disks']['persistent'].delete(disk_cid)
657
+ @logger.info("Updating agent env to: #{env.pretty_inspect}")
740
658
 
659
+ @agent_env.set_env(vm_mob, location, env)
660
+ end
661
+ end
741
662
  end
742
663
  end
@@ -157,10 +157,7 @@ module VSphereCloud
157
157
  'datastore_pattern' => String,
158
158
  'persistent_datastore_pattern' => String,
159
159
  optional('allow_mixed_datastores') => bool,
160
- 'clusters' => [enum(String,
161
- dict(String, {
162
- 'resource_pool' => String
163
- })
160
+ 'clusters' => [enum(String, dict(String, {optional('resource_pool') => String})
164
161
  )]
165
162
  }]
166
163
  }]
@@ -1,7 +1,7 @@
1
1
  require 'cloud/vsphere/resources/resource_pool'
2
2
 
3
3
  module VSphereCloud
4
- class Resources
4
+ module Resources
5
5
  class Cluster
6
6
  include VimSdk
7
7
  include ObjectStringifier
@@ -11,6 +11,8 @@ module VSphereCloud
11
11
  HOST_PROPERTIES = %w(hardware.memorySize runtime.inMaintenanceMode)
12
12
  HOST_COUNTERS = %w(mem.usage.average)
13
13
 
14
+ MEMORY_HEADROOM = 128
15
+
14
16
  # @!attribute mob
15
17
  # @return [Vim::ClusterComputeResource] cluster vSphere MOB.
16
18
  attr_reader :mob
@@ -80,24 +82,6 @@ module VSphereCloud
80
82
  @allocated_after_sync += memory
81
83
  end
82
84
 
83
- # Picks the best datastore for the specified persistent disk.
84
- #
85
- # @param [Integer] size persistent disk size.
86
- # @return [Datastore] the best datastore for the requested size.
87
- # @raise [Bosh::Clouds::NoDiskSpace] if no datastore available for the requested size
88
- def pick_persistent(size)
89
- pick_store(:persistent, size)
90
- end
91
-
92
- # Picks the best datastore for the specified ephemeral disk.
93
- #
94
- # @param [Integer] size ephemeral disk size.
95
- # @return [Datastore] the best datastore for the requested size.
96
- # @raise [Bosh::Clouds::NoDiskSpace] if no datastore available for the requested size
97
- def pick_ephemeral(size)
98
- pick_store(:ephemeral, size)
99
- end
100
-
101
85
  # @return [String] cluster name.
102
86
  def name
103
87
  config.name
@@ -108,6 +92,13 @@ module VSphereCloud
108
92
  "<Cluster: #{mob} / #{config.name}>"
109
93
  end
110
94
 
95
+ # @return [String] more descriptive debug cluster information.
96
+ def describe
97
+ "#{name} has #{free_memory}mb/" +
98
+ "#{total_free_ephemeral_disk_in_mb / 1024}gb/" +
99
+ "#{total_free_persistent_disk_in_mb / 1024}gb"
100
+ end
101
+
111
102
  def ephemeral_datastores
112
103
  @ephemeral_datastores ||= select_datastores(@datacenter_datastore_pattern)
113
104
  end
@@ -134,22 +125,6 @@ module VSphereCloud
134
125
  all_datastores.select { |name, datastore| name =~ pattern }
135
126
  end
136
127
 
137
- def pick_store(type, size)
138
- datastores = (type == :ephemeral ? ephemeral_datastores : persistent_datastores).values
139
- available_datastores = datastores.reject { |datastore| datastore.free_space - size < DISK_HEADROOM }
140
-
141
- @logger.debug("Looking for a #{type} datastore in #{self.name} with #{size}MB free space.")
142
- @logger.debug("All datastores within cluster #{self.name}: #{datastores.map(&:debug_info)}")
143
- @logger.debug("Datastores with enough space: #{available_datastores.map(&:debug_info)}")
144
-
145
- selected_datastore = Util.weighted_random(available_datastores.map { |datastore| [datastore, datastore.free_space] })
146
-
147
- if selected_datastore.nil?
148
- raise Bosh::Clouds::NoDiskSpace.new(true), "Couldn't find a #{type} datastore with #{size}MB of free space accessible from cluster '#{self.name}'. Found:\n #{datastores.map(&:debug_info).join("\n ")}\n"
149
- end
150
- selected_datastore
151
- end
152
-
153
128
  def synced_free_memory
154
129
  return @synced_free_memory if @synced_free_memory
155
130
  # Have to use separate mechanisms for fetching utilization depending on
@@ -1,5 +1,5 @@
1
1
  module VSphereCloud
2
- class Resources
2
+ module Resources
3
3
  class ClusterProvider
4
4
  def initialize(datacenter, client, logger)
5
5
  @datacenter = datacenter