chef-provisioning-vsphere 0.5.7.dev6 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a2f55b3a6433abfdd06aa270db00b1bed0cb8ab
4
- data.tar.gz: 74c8800daf24128394246648b0e02540ac0485e8
3
+ metadata.gz: e7308c027bc21589567543a1144202d7b8868641
4
+ data.tar.gz: 0f7ce9c37b7ae5662446ca99feb473c61fbbb6ce
5
5
  SHA512:
6
- metadata.gz: 56b566ca067ed38e6d7b639d6a687468b1189be2693bcd608cd85753d98cba8361009f00e145bf2ee2f9dffc8c766898767787f6f1b9177b73271a5dbc3359ce
7
- data.tar.gz: a01d8b591d62cd589569f868e3aa606c1f133f6a099caaab60534628848a56168014d3cd0a95a6722c86d61d8594ca743fe2ff0add2919ca5706ddb99da1cbcf
6
+ metadata.gz: f9c2f84cabb77cd7cc0540e3a4c648129d97360d4430d2c6ff9d1dd31f1afeb3429191aae723e82c8b2c5c033af5a6e54c779aebf4de851df138ce68a6ae02ec
7
+ data.tar.gz: 5fa9251bbca1fe98791fe01d27bdf015118d32f5c1832172d0bdf4af075b5fb6d07ba8a13170773628a540852f32d5026c7b3b1e8e374a3a515ca899a2fc2c1e
@@ -3,7 +3,6 @@ require 'cheffish/merged_config'
3
3
  require 'chef/provisioning/driver'
4
4
  require 'chef/provisioning/machine/windows_machine'
5
5
  require 'chef/provisioning/machine/unix_machine'
6
- require 'chef/provisioning/vsphere_driver/clone_spec_builder'
7
6
  require 'chef/provisioning/vsphere_driver/version'
8
7
  require 'chef/provisioning/vsphere_driver/vsphere_helpers'
9
8
  require 'chef/provisioning/vsphere_driver/vsphere_url'
@@ -12,6 +11,7 @@ module ChefProvisioningVsphere
12
11
  # Provisions machines in vSphere.
13
12
  class VsphereDriver < Chef::Provisioning::Driver
14
13
  include Chef::Mixin::ShellOut
14
+ include ChefProvisioningVsphere::Helpers
15
15
 
16
16
  def self.from_url(driver_url, config)
17
17
  VsphereDriver.new(driver_url, config)
@@ -163,7 +163,7 @@ module ChefProvisioningVsphere
163
163
  end
164
164
 
165
165
  def find_or_create_vm(bootstrap_options, machine_spec, action_handler)
166
- vm = vsphere_helper.find_vm(
166
+ vm = find_vm(
167
167
  bootstrap_options[:vm_folder],
168
168
  machine_spec.name
169
169
  )
@@ -231,7 +231,7 @@ module ChefProvisioningVsphere
231
231
  end
232
232
  return if networks.nil? || networks.count < 2
233
233
 
234
- new_nics = vsphere_helper.add_extra_nic(
234
+ new_nics = add_extra_nic(
235
235
  action_handler,
236
236
  vm_template_for(bootstrap_options),
237
237
  bootstrap_options,
@@ -313,7 +313,7 @@ module ChefProvisioningVsphere
313
313
  msg << vm.guest.toolsRunningStatus
314
314
  msg << '. powering up server...'
315
315
  action_handler.report_progress(msg.join)
316
- vsphere_helper.start_vm(vm)
316
+ start_vm(vm)
317
317
  else
318
318
  restart_server(action_handler, machine_spec, machine_options)
319
319
  end
@@ -395,7 +395,7 @@ module ChefProvisioningVsphere
395
395
  vm = vm_for(machine_spec)
396
396
  if vm
397
397
  action_handler.perform_action "Shutdown guest OS and power off VM [#{vm.parent.name}/#{vm.name}]" do
398
- vsphere_helper.stop_vm(vm)
398
+ stop_vm(vm)
399
399
  end
400
400
  end
401
401
  end
@@ -405,7 +405,7 @@ module ChefProvisioningVsphere
405
405
  vm = vm_for(machine_spec)
406
406
  if vm
407
407
  action_handler.perform_action "Power on VM [#{vm.parent.name}/#{vm.name}]" do
408
- vsphere_helper.start_vm(vm, machine_options[:bootstrap_options][:ssh][:port])
408
+ start_vm(vm, machine_options[:bootstrap_options][:ssh][:port])
409
409
  end
410
410
  end
411
411
  vm
@@ -484,53 +484,25 @@ module ChefProvisioningVsphere
484
484
 
485
485
  def vm_for(machine_spec)
486
486
  if machine_spec.location
487
- vsphere_helper.find_vm_by_id(machine_spec.location['server_id'])
487
+ find_vm_by_id(machine_spec.location['server_id'])
488
488
  else
489
489
  nil
490
490
  end
491
491
  end
492
492
 
493
493
  def clone_vm(action_handler, bootstrap_options, machine_name)
494
- vm_template = vm_template_for(bootstrap_options)
495
-
496
- spec_builder = CloneSpecBuilder.new(vsphere_helper, action_handler)
497
- clone_spec = spec_builder.build(vm_template, machine_name, bootstrap_options)
498
- Chef::Log.debug("Clone spec: #{clone_spec.pretty_inspect}")
499
-
500
- vm_folder = vsphere_helper.find_folder(bootstrap_options[:vm_folder])
501
- vm_template.CloneVM_Task(
502
- name: machine_name,
503
- folder: vm_folder,
504
- spec: clone_spec
505
- ).wait_for_completion
506
-
507
- vm = vsphere_helper.find_vm(vm_folder, machine_name)
508
-
509
- if bootstrap_options[:additional_disk_size_gb].to_i > 0
510
- task = vm.ReconfigVM_Task(
511
- spec: RbVmomi::VIM.VirtualMachineConfigSpec(
512
- deviceChange: [
513
- vsphere_helper.virtual_disk_for(vm, bootstrap_options)
514
- ]
515
- )
516
- )
517
- task.wait_for_completion
518
- end
519
-
520
- vm
521
- end
522
-
523
- def vsphere_helper
524
- @vsphere_helper ||= VsphereHelper.new(
525
- connect_options,
526
- config[:machine_options][:bootstrap_options][:datacenter]
494
+ do_vm_clone(
495
+ action_handler,
496
+ vm_template_for(bootstrap_options),
497
+ machine_name,
498
+ bootstrap_options
527
499
  )
528
500
  end
529
501
 
530
502
  def vm_template_for(bootstrap_options)
531
503
  template_folder = bootstrap_options[:template_folder]
532
504
  template_name = bootstrap_options[:template_name]
533
- vsphere_helper.find_vm(template_folder, template_name) ||
505
+ find_vm(template_folder, template_name) ||
534
506
  raise("vSphere VM Template not found [#{template_folder}/#{template_name}]")
535
507
  end
536
508
 
@@ -1,3 +1,3 @@
1
1
  module ChefProvisioningVsphere
2
- VERSION = '0.5.7.dev6'
2
+ VERSION = '0.5.7'
3
3
  end
@@ -1,24 +1,16 @@
1
1
  require 'rbvmomi'
2
2
 
3
3
  module ChefProvisioningVsphere
4
- class VsphereHelper
4
+ module Helpers
5
5
 
6
6
  if !$guest_op_managers
7
7
  $guest_op_managers = {}
8
8
  end
9
9
 
10
- def initialize(connect_options, datacenter_name)
11
- @connect_options = connect_options
12
- @datacenter_name = datacenter_name
13
- end
14
-
15
- attr_reader :connect_options
16
- attr_reader :datacenter_name
17
-
18
- def vim
10
+ def vim(options = connect_options)
19
11
  if @current_connection.nil? or @current_connection.serviceContent.sessionManager.currentSession.nil?
20
- puts "establishing connection to #{connect_options[:host]}"
21
- @current_connection = RbVmomi::VIM.connect connect_options
12
+ puts "establishing connection to #{options[:host]}"
13
+ @current_connection = RbVmomi::VIM.connect options
22
14
  str_conn = @current_connection.pretty_inspect # a string in the format of VIM(host ip)
23
15
 
24
16
  # we are caching guest operation managers in a global variable...terrible i know
@@ -39,14 +31,22 @@ module ChefProvisioningVsphere
39
31
  folder.find(vm_name, RbVmomi::VIM::VirtualMachine)
40
32
  end
41
33
 
42
- def find_vm_by_id(uuid)
43
- vm = vim.searchIndex.FindByUuid(
34
+ def find_vm_by_id(uuid, connection = vim)
35
+ vm = connection.searchIndex.FindByUuid(
44
36
  uuid: uuid,
45
37
  vmSearch: true,
46
38
  instanceUuid: true
47
39
  )
48
40
  end
49
41
 
42
+ def vm_started?(vm, wait_on_port = 22)
43
+ return false if vm.nil?
44
+ state = vm.runtime.powerState
45
+ return false unless state == 'poweredOn'
46
+ return false unless port_ready?(vm, wait_on_port)
47
+ return true
48
+ end
49
+
50
50
  def vm_stopped?(vm)
51
51
  return true if vm.nil?
52
52
  state = vm.runtime.powerState
@@ -70,6 +70,31 @@ module ChefProvisioningVsphere
70
70
  end
71
71
  end
72
72
 
73
+ def port_ready?(vm, port)
74
+ vm_ip = vm.guest.ipAddress
75
+ return false if vm_ip.nil?
76
+
77
+ begin
78
+ tcp_socket = TCPSocket.new(vm_ip, port)
79
+ readable = IO.select([tcp_socket], nil, nil, 5)
80
+ if readable
81
+ true
82
+ else
83
+ false
84
+ end
85
+ rescue Errno::ETIMEDOUT
86
+ false
87
+ rescue Errno::EPERM
88
+ false
89
+ rescue Errno::ECONNREFUSED
90
+ false
91
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
92
+ false
93
+ ensure
94
+ tcp_socket && tcp_socket.close
95
+ end
96
+ end
97
+
73
98
  #folder could be like: /Level1/Level2/folder_name
74
99
  def find_folder(folder_name)
75
100
  base = datacenter.vmFolder
@@ -83,8 +108,9 @@ module ChefProvisioningVsphere
83
108
  end
84
109
 
85
110
  def datacenter
86
- @datacenter ||= vim.serviceInstance.find_datacenter(datacenter_name) ||
87
- raise("vSphere Datacenter not found [#{datacenter_name}]")
111
+ dc_name = config[:machine_options][:bootstrap_options][:datacenter]
112
+ @datacenter ||= vim.serviceInstance.find_datacenter(dc_name) ||
113
+ raise("vSphere Datacenter not found [#{dc_name}]")
88
114
  end
89
115
 
90
116
  def network_adapter_for(operation, network_name, network_label, device_key, backing_info)
@@ -106,6 +132,56 @@ module ChefProvisioningVsphere
106
132
  vm.config.hardware.device.select {|d| d.is_a?(RbVmomi::VIM::VirtualEthernetCard)}
107
133
  end
108
134
 
135
+ def do_vm_clone(action_handler, vm_template, vm_name, options)
136
+ deviceAdditions = []
137
+
138
+ clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(
139
+ location: relocate_spec_for(vm_template, options),
140
+ powerOn: false,
141
+ template: false,
142
+ config: RbVmomi::VIM.VirtualMachineConfigSpec(
143
+ :cpuHotAddEnabled => true,
144
+ :memoryHotAddEnabled => true,
145
+ :cpuHotRemoveEnabled => true,
146
+ :deviceChange => Array.new)
147
+ )
148
+
149
+ clone_spec.customization = customization_options_from(action_handler, vm_template, vm_name, options)
150
+
151
+ unless options[:annotation].to_s.nil?
152
+ clone_spec.config.annotation = options[:annotation]
153
+ end
154
+
155
+ unless options[:num_cpus].to_s.nil?
156
+ clone_spec.config.numCPUs = options[:num_cpus]
157
+ end
158
+
159
+ unless options[:memory_mb].to_s.nil?
160
+ clone_spec.config.memoryMB = options[:memory_mb]
161
+ end
162
+
163
+ unless options[:network_name].nil?
164
+ deviceAdditions, changes = network_device_changes(action_handler, vm_template, options)
165
+ clone_spec.config.deviceChange = changes
166
+ end
167
+
168
+ vm_folder = find_folder(options[:vm_folder])
169
+ vm_template.CloneVM_Task(
170
+ name: vm_name,
171
+ folder: vm_folder,
172
+ spec: clone_spec
173
+ ).wait_for_completion
174
+
175
+ vm = find_vm(vm_folder, vm_name)
176
+
177
+ if options[:additional_disk_size_gb].to_i > 0
178
+ task = vm.ReconfigVM_Task(:spec => RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange => [virtual_disk_for(vm, options)]))
179
+ task.wait_for_completion
180
+ end
181
+
182
+ vm
183
+ end
184
+
109
185
  def add_extra_nic(action_handler, vm_template, options, vm)
110
186
  deviceAdditions, changes = network_device_changes(action_handler, vm_template, options)
111
187
 
@@ -130,6 +206,28 @@ module ChefProvisioningVsphere
130
206
  end
131
207
  end
132
208
 
209
+ def relocate_spec_for(vm_template, options)
210
+ if options.has_key?(:host)
211
+ host = find_host(options[:host])
212
+ rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(host: host)
213
+ else
214
+ pool = options[:resource_pool] ? find_pool(options[:resource_pool]) : vm_template.resourcePool
215
+ rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: pool)
216
+ raise 'either :host or :resource_pool must be specified when cloning from a VM Template' if pool.nil?
217
+ end
218
+
219
+ if options.has_key?(:use_linked_clone)
220
+ create_delta_disk(vm_template)
221
+ rspec.diskMoveType = :moveChildMostDiskBacking
222
+ end
223
+
224
+ unless options[:datastore].to_s.empty?
225
+ rspec.datastore = find_datastore(options[:datastore])
226
+ end
227
+
228
+ rspec
229
+ end
230
+
133
231
  def create_delta_disk(vm_template)
134
232
  disks = vm_template.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
135
233
  disks.select { |disk| disk.backing.parent == nil }.each do |disk|
@@ -228,12 +326,114 @@ module ChefProvisioningVsphere
228
326
  datacenter.datastore.find { |f| f.info.name == datastore_name } or raise "no such datastore #{datastore_name}"
229
327
  end
230
328
 
329
+ def customization_options_from(action_handler, vm_template, vm_name, options)
330
+ if options.has_key?(:customization_spec)
331
+ if(options[:customization_spec].is_a?(Hash))
332
+ cust_options = options[:customization_spec]
333
+ ip_settings = cust_options[:ipsettings]
334
+ cust_domain = cust_options[:domain]
335
+
336
+ raise ArgumentError, 'domain is required' unless cust_domain
337
+ cust_ip_settings = nil
338
+ if ip_settings && ip_settings.key?(:ip)
339
+ unless cust_options[:ipsettings].key?(:subnetMask)
340
+ raise ArgumentError, 'subnetMask is required for static ip'
341
+ end
342
+ cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(ip_settings)
343
+ action_handler.report_progress "customizing #{vm_name} with static IP #{ip_settings[:ip]}"
344
+ cust_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp(:ipAddress => ip_settings[:ip])
345
+ end
346
+ if cust_ip_settings.nil?
347
+ cust_ip_settings= RbVmomi::VIM::CustomizationIPSettings.new(:ip => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
348
+ cust_ip_settings.dnsServerList = ip_settings[:dnsServerList]
349
+ action_handler.report_progress "customizing #{vm_name} with dynamic IP and DNS: #{ip_settings[:dnsServerList]}"
350
+ end
351
+
352
+ cust_ip_settings.dnsDomain = cust_domain
353
+ cust_global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
354
+ cust_global_ip_settings.dnsServerList = cust_ip_settings.dnsServerList
355
+ cust_global_ip_settings.dnsSuffixList = [cust_domain]
356
+ cust_hostname = hostname_from(cust_options, vm_name)
357
+ cust_hwclockutc = cust_options[:hw_clock_utc]
358
+ cust_timezone = cust_options[:time_zone]
359
+
360
+ if vm_template.config.guestId.start_with?('win')
361
+ cust_prep = windows_prep_for(action_handler, options, vm_name)
362
+ else
363
+ cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
364
+ :domain => cust_domain,
365
+ :hostName => cust_hostname,
366
+ :hwClockUTC => cust_hwclockutc,
367
+ :timeZone => cust_timezone
368
+ )
369
+ end
370
+ cust_adapter_mapping = [RbVmomi::VIM::CustomizationAdapterMapping.new(:adapter => cust_ip_settings)]
371
+ RbVmomi::VIM::CustomizationSpec.new(
372
+ :identity => cust_prep,
373
+ :globalIPSettings => cust_global_ip_settings,
374
+ :nicSettingMap => cust_adapter_mapping
375
+ )
376
+ else
377
+ find_customization_spec(cust_options)
378
+ end
379
+ end
380
+ end
381
+
382
+ def windows_prep_for(action_handler, options, vm_name)
383
+ cust_options = options[:customization_spec]
384
+ cust_runonce = RbVmomi::VIM::CustomizationGuiRunOnce.new(
385
+ :commandList => [
386
+ 'winrm set winrm/config/client/auth @{Basic="true"}',
387
+ 'winrm set winrm/config/service/auth @{Basic="true"}',
388
+ 'winrm set winrm/config/service @{AllowUnencrypted="true"}',
389
+ 'shutdown -l'])
390
+
391
+ cust_login_password = RbVmomi::VIM::CustomizationPassword(
392
+ :plainText => true,
393
+ :value => options[:ssh][:password])
394
+ if cust_options.has_key?(:domain) and cust_options[:domain] != 'local'
395
+ cust_domain_password = RbVmomi::VIM::CustomizationPassword(
396
+ :plainText => true,
397
+ :value => ENV['domainAdminPassword'] || cust_options[:domainAdminPassword])
398
+ cust_id = RbVmomi::VIM::CustomizationIdentification.new(
399
+ :joinDomain => cust_options[:domain],
400
+ :domainAdmin => cust_options[:domainAdmin],
401
+ :domainAdminPassword => cust_domain_password)
402
+ #puts "my env passwd is: #{ENV['domainAdminPassword']}"
403
+ action_handler.report_progress "joining domain #{cust_options[:domain]} with user: #{cust_options[:domainAdmin]}"
404
+ else
405
+ cust_id = RbVmomi::VIM::CustomizationIdentification.new(
406
+ :joinWorkgroup => 'WORKGROUP')
407
+ end
408
+ cust_gui_unattended = RbVmomi::VIM::CustomizationGuiUnattended.new(
409
+ :autoLogon => true,
410
+ :autoLogonCount => 1,
411
+ :password => cust_login_password,
412
+ :timeZone => cust_options[:win_time_zone])
413
+ cust_userdata = RbVmomi::VIM::CustomizationUserData.new(
414
+ :computerName => hostname_from(cust_options, vm_name),
415
+ :fullName => cust_options[:org_name],
416
+ :orgName => cust_options[:org_name],
417
+ :productId => cust_options[:product_id])
418
+ RbVmomi::VIM::CustomizationSysprep.new(
419
+ :guiRunOnce => cust_runonce,
420
+ :identification => cust_id,
421
+ :guiUnattended => cust_gui_unattended,
422
+ :userData => cust_userdata)
423
+ end
424
+
425
+ def hostname_from(options, vm_name)
426
+ if options.key?(:hostname)
427
+ RbVmomi::VIM::CustomizationFixedName.new(:name => options[:hostname])
428
+ else
429
+ RbVmomi::VIM::CustomizationFixedName.new(:name => vm_name)
430
+ end
431
+ end
432
+
231
433
  def find_entity(name, parent_folder, &block)
232
434
  parts = name.split('/').reject(&:empty?)
233
435
  parts.each do |item|
234
- Chef::Log.debug("Identifying entity part: #{item} in folder type: #{parent_folder.class}")
235
436
  if parent_folder.is_a? RbVmomi::VIM::Folder
236
- Chef::Log.debug('Parent folder is a folder')
237
437
  parent_folder = parent_folder.childEntity.find { |f| f.name == item }
238
438
  else
239
439
  parent_folder = block.call(parent_folder, item)
@@ -256,28 +456,20 @@ module ChefProvisioningVsphere
256
456
 
257
457
  raise "vSphere Host not found [#{host_name}]" if host.nil?
258
458
 
259
- if host.is_a?(RbVmomi::VIM::ComputeResource)
260
- host = host.host.first
459
+ if !host.is_a?(RbVmomi::VIM::HostSystem) && host.respond_to?(:host)
460
+ host = host.host
261
461
  end
262
462
  host
263
463
  end
264
464
 
265
465
  def find_pool(pool_name)
266
- Chef::Log.debug("Finding pool: #{pool_name}")
267
466
  pool = find_entity(pool_name, datacenter.hostFolder) do |parent, part|
268
467
  case parent
269
- when RbVmomi::VIM::ClusterComputeResource, RbVmomi::VIM::ComputeResource
270
- Chef::Log.debug("finding #{part} in a #{parent.class}: #{parent.name}")
271
- Chef::Log.debug("Parent root pool has #{parent.resourcePool.resourcePool.count} pools")
272
- parent.resourcePool.resourcePool.each { |p| Chef::Log.debug(p.name ) }
468
+ when RbVmomi::VIM::ClusterComputeResource || RbVmomi::VIM::ComputeResource
273
469
  parent.resourcePool.resourcePool.find { |f| f.name == part }
274
470
  when RbVmomi::VIM::ResourcePool
275
- Chef::Log.debug("finding #{part} in a Resource Pool: #{parent.name}")
276
- Chef::Log.debug("Pool has #{parent.resourcePool.count} pools")
277
- parent.resourcePool.each { |p| Chef::Log.debug(p.name ) }
278
471
  parent.resourcePool.find { |f| f.name == part }
279
472
  else
280
- Chef::Log.debug("parent of #{part} is unexpected type: #{parent.class}")
281
473
  nil
282
474
  end
283
475
  end
@@ -34,11 +34,12 @@ require 'chef/provisioning/machine_spec'
34
34
  # }
35
35
 
36
36
  describe 'vsphere_driver' do
37
+ include ChefProvisioningVsphere::Helpers
38
+
37
39
  before :all do
38
40
  @vm_name = "cmvd-test-#{SecureRandom.hex}"
39
41
  @metal_config = eval File.read(File.expand_path('../config.rb', __FILE__))
40
42
  Cheffish.honor_local_mode do
41
- Chef::Log.level = :debug
42
43
  chef_server = Cheffish.default_chef_server
43
44
  @machine_spec = Chef::Provisioning.chef_managed_entry_store(chef_server).new_entry(:machine, @vm_name)
44
45
  url = URI::VsphereUrl.from_config(@metal_config[:driver_options]).to_s
@@ -48,11 +49,8 @@ describe 'vsphere_driver' do
48
49
  @metal_config[:machine_options][:convergence_options] = {:chef_server => chef_server}
49
50
  machine = @driver.ready_machine(action_handler, @machine_spec, @metal_config[:machine_options])
50
51
  @server_id = @machine_spec.location['server_id']
51
- @vsphere_helper = ChefProvisioningVsphere::VsphereHelper.new(
52
- @metal_config[:driver_options],
53
- @metal_config[:machine_options][:bootstrap_options][:datacenter]
54
- )
55
- @vm = @vsphere_helper.find_vm_by_id(@server_id)
52
+ @connection = vim(@metal_config[:driver_options])
53
+ @vm = find_vm_by_id(@server_id, @connection)
56
54
  end
57
55
  end
58
56
 
@@ -103,7 +101,7 @@ describe 'vsphere_driver' do
103
101
  end
104
102
  end
105
103
  it 'is in the correct datacenter' do
106
- expect(@vsphere_helper.vim.serviceInstance.find_datacenter(@metal_config[:machine_options][:bootstrap_options][:datacenter]).find_vm("#{@vm.parent.name}/#{@vm_name}")).not_to eq(nil)
104
+ expect(@connection.serviceInstance.find_datacenter(@metal_config[:machine_options][:bootstrap_options][:datacenter]).find_vm("#{@vm.parent.name}/#{@vm_name}")).not_to eq(nil)
107
105
  end
108
106
  it 'has an added disk of the correct size' do
109
107
  disk_count = @vm.disks.count
@@ -148,7 +146,7 @@ describe 'vsphere_driver' do
148
146
  @metal_config[:machine_options]
149
147
  )
150
148
  end
151
- vm = @vsphere_helper.find_vm_by_id(@server_id)
149
+ vm = find_vm_by_id(@server_id, @connection)
152
150
  expect(vm).to eq(nil)
153
151
  end
154
152
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-provisioning-vsphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.7.dev6
4
+ version: 0.5.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - CenturyLink Cloud
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-15 00:00:00.000000000 Z
11
+ date: 2015-06-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rbvmomi
@@ -103,7 +103,6 @@ files:
103
103
  - contribution-notice
104
104
  - lib/chef/provisioning/driver_init/vsphere.rb
105
105
  - lib/chef/provisioning/vsphere_driver.rb
106
- - lib/chef/provisioning/vsphere_driver/clone_spec_builder.rb
107
106
  - lib/chef/provisioning/vsphere_driver/driver.rb
108
107
  - lib/chef/provisioning/vsphere_driver/version.rb
109
108
  - lib/chef/provisioning/vsphere_driver/vsphere_helpers.rb
@@ -113,8 +112,6 @@ files:
113
112
  - spec/integration_tests/vsphere_driver_spec.rb
114
113
  - spec/unit_tests/VsphereDriver_spec.rb
115
114
  - spec/unit_tests/VsphereUrl_spec.rb
116
- - spec/unit_tests/clone_spec_builder_spec.rb
117
- - spec/unit_tests/support/vsphere_helper_stub.rb
118
115
  homepage: https://github.com/tier3/chef-provisioning-vsphere
119
116
  licenses:
120
117
  - MIT
@@ -130,9 +127,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
130
127
  version: '0'
131
128
  required_rubygems_version: !ruby/object:Gem::Requirement
132
129
  requirements:
133
- - - ">"
130
+ - - ">="
134
131
  - !ruby/object:Gem::Version
135
- version: 1.3.1
132
+ version: '0'
136
133
  requirements: []
137
134
  rubyforge_project:
138
135
  rubygems_version: 2.4.4
@@ -144,6 +141,4 @@ test_files:
144
141
  - spec/integration_tests/vsphere_driver_spec.rb
145
142
  - spec/unit_tests/VsphereDriver_spec.rb
146
143
  - spec/unit_tests/VsphereUrl_spec.rb
147
- - spec/unit_tests/clone_spec_builder_spec.rb
148
- - spec/unit_tests/support/vsphere_helper_stub.rb
149
144
  has_rdoc:
@@ -1,200 +0,0 @@
1
- module ChefProvisioningVsphere
2
- class CloneSpecBuilder
3
- def initialize(vsphere_helper, action_handler)
4
- @vsphere_helper = vsphere_helper
5
- @action_handler = action_handler
6
- end
7
-
8
- attr_reader :vsphere_helper
9
- attr_reader :action_handler
10
-
11
- def build(vm_template, vm_name, options)
12
- clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(
13
- location: relocate_spec_for(vm_template, options),
14
- powerOn: false,
15
- template: false,
16
- config: RbVmomi::VIM.VirtualMachineConfigSpec(
17
- :cpuHotAddEnabled => true,
18
- :memoryHotAddEnabled => true,
19
- :cpuHotRemoveEnabled => true,
20
- :deviceChange => Array.new)
21
- )
22
-
23
- unless options[:annotation].to_s.nil?
24
- clone_spec.config.annotation = options[:annotation]
25
- end
26
-
27
- unless options[:num_cpus].to_s.nil?
28
- clone_spec.config.numCPUs = options[:num_cpus]
29
- end
30
-
31
- unless options[:memory_mb].to_s.nil?
32
- clone_spec.config.memoryMB = options[:memory_mb]
33
- end
34
-
35
- unless options[:network_name].nil?
36
- deviceAdditions, changes = vsphere_helper.network_device_changes(
37
- action_handler,
38
- vm_template,
39
- options
40
- )
41
- clone_spec.config.deviceChange = changes
42
- end
43
-
44
- clone_spec.customization = customization_options_from(
45
- vm_template,
46
- vm_name,
47
- options
48
- )
49
-
50
- clone_spec
51
- end
52
-
53
- def relocate_spec_for(vm_template, options)
54
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec
55
- host = nil
56
-
57
- if options.has_key?(:host)
58
- host = vsphere_helper.find_host(options[:host])
59
- rspec.host = host
60
- end
61
-
62
- if options[:resource_pool]
63
- rspec.pool = vsphere_helper.find_pool(options[:resource_pool])
64
- elsif vm_template.config.template && !host.nil?
65
- rspec.pool = host.parent.resourcePool # assign to the "invisible" pool root
66
- elsif vm_template.config.template
67
- raise 'either :host or :resource_pool must be specified when cloning from a VM Template'
68
- end
69
-
70
-
71
- if options[:use_linked_clone]
72
- if vm_template.config.template
73
- Chef::Log.warn("Using a VM Template, ignoring use_linked_clone.")
74
- else
75
- vsphere_helper.create_delta_disk(vm_template)
76
- rspec.diskMoveType = :moveChildMostDiskBacking
77
- end
78
- end
79
-
80
- unless options[:datastore].to_s.empty?
81
- rspec.datastore = vsphere_helper.find_datastore(options[:datastore])
82
- end
83
-
84
- rspec
85
- end
86
-
87
- def customization_options_from(vm_template, vm_name, options)
88
- if options.has_key?(:customization_spec)
89
- if(options[:customization_spec].is_a?(Hash))
90
- cust_options = options[:customization_spec]
91
- ip_settings = cust_options[:ipsettings]
92
- cust_domain = cust_options[:domain]
93
-
94
- raise ArgumentError, 'domain is required' unless cust_domain
95
- cust_ip_settings = nil
96
- if ip_settings && ip_settings.key?(:ip)
97
- unless cust_options[:ipsettings].key?(:subnetMask)
98
- raise ArgumentError, 'subnetMask is required for static ip'
99
- end
100
- cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(
101
- ip_settings)
102
- action_handler.report_progress "customizing #{vm_name} \
103
- with static IP #{ip_settings[:ip]}"
104
- cust_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp(
105
- :ipAddress => ip_settings[:ip])
106
- end
107
- if cust_ip_settings.nil?
108
- cust_ip_settings= RbVmomi::VIM::CustomizationIPSettings.new(
109
- :ip => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
110
- cust_ip_settings.dnsServerList = ip_settings[:dnsServerList]
111
- action_handler.report_progress "customizing #{vm_name} with /
112
- dynamic IP and DNS: #{ip_settings[:dnsServerList]}"
113
- end
114
-
115
- cust_ip_settings.dnsDomain = cust_domain
116
- global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
117
- global_ip_settings.dnsServerList = cust_ip_settings.dnsServerList
118
- global_ip_settings.dnsSuffixList = [cust_domain]
119
- cust_hostname = hostname_from(cust_options, vm_name)
120
- cust_hwclockutc = cust_options[:hw_clock_utc]
121
- cust_timezone = cust_options[:time_zone]
122
-
123
- if vm_template.config.guestId.start_with?('win')
124
- cust_prep = windows_prep_for(options, vm_name)
125
- else
126
- cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
127
- :domain => cust_domain,
128
- :hostName => cust_hostname,
129
- :hwClockUTC => cust_hwclockutc,
130
- :timeZone => cust_timezone
131
- )
132
- end
133
- cust_adapter_mapping = [
134
- RbVmomi::VIM::CustomizationAdapterMapping.new(
135
- :adapter => cust_ip_settings)
136
- ]
137
- RbVmomi::VIM::CustomizationSpec.new(
138
- :identity => cust_prep,
139
- :globalIPSettings => global_ip_settings,
140
- :nicSettingMap => cust_adapter_mapping
141
- )
142
- else
143
- vsphere_helper.find_customization_spec(cust_options)
144
- end
145
- end
146
- end
147
-
148
- def hostname_from(options, vm_name)
149
- if options.key?(:hostname)
150
- RbVmomi::VIM::CustomizationFixedName.new(:name => options[:hostname])
151
- else
152
- RbVmomi::VIM::CustomizationFixedName.new(:name => vm_name)
153
- end
154
- end
155
-
156
- def windows_prep_for(options, vm_name)
157
- cust_options = options[:customization_spec]
158
- cust_runonce = RbVmomi::VIM::CustomizationGuiRunOnce.new(
159
- :commandList => [
160
- 'winrm set winrm/config/client/auth @{Basic="true"}',
161
- 'winrm set winrm/config/service/auth @{Basic="true"}',
162
- 'winrm set winrm/config/service @{AllowUnencrypted="true"}',
163
- 'shutdown -l'])
164
-
165
- cust_login_password = RbVmomi::VIM::CustomizationPassword(
166
- :plainText => true,
167
- :value => options[:ssh][:password])
168
- if cust_options.has_key?(:domain) and cust_options[:domain] != 'local'
169
- cust_domain_password = RbVmomi::VIM::CustomizationPassword(
170
- :plainText => true,
171
- :value => ENV['domainAdminPassword'] || cust_options[:domainAdminPassword])
172
- cust_id = RbVmomi::VIM::CustomizationIdentification.new(
173
- :joinDomain => cust_options[:domain],
174
- :domainAdmin => cust_options[:domainAdmin],
175
- :domainAdminPassword => cust_domain_password)
176
- #puts "my env passwd is: #{ENV['domainAdminPassword']}"
177
- action_handler.report_progress "joining domain #{cust_options[:domain]} /
178
- with user: #{cust_options[:domainAdmin]}"
179
- else
180
- cust_id = RbVmomi::VIM::CustomizationIdentification.new(
181
- :joinWorkgroup => 'WORKGROUP')
182
- end
183
- cust_gui_unattended = RbVmomi::VIM::CustomizationGuiUnattended.new(
184
- :autoLogon => true,
185
- :autoLogonCount => 1,
186
- :password => cust_login_password,
187
- :timeZone => cust_options[:win_time_zone])
188
- cust_userdata = RbVmomi::VIM::CustomizationUserData.new(
189
- :computerName => hostname_from(cust_options, vm_name),
190
- :fullName => cust_options[:org_name],
191
- :orgName => cust_options[:org_name],
192
- :productId => cust_options[:product_id])
193
- RbVmomi::VIM::CustomizationSysprep.new(
194
- :guiRunOnce => cust_runonce,
195
- :identification => cust_id,
196
- :guiUnattended => cust_gui_unattended,
197
- :userData => cust_userdata)
198
- end
199
- end
200
- end
@@ -1,102 +0,0 @@
1
- require 'chef/provisioning/vsphere_driver'
2
-
3
- require_relative 'support/vsphere_helper_stub'
4
-
5
- describe ChefProvisioningVsphere::CloneSpecBuilder do
6
- let(:options) { Hash.new }
7
- let(:vm_template) { double('template') }
8
-
9
- before do
10
- allow(vm_template).to receive_message_chain(:config, :guestId)
11
- allow(vm_template).to receive_message_chain(:config, :template)
12
- .and_return(false)
13
- end
14
-
15
- subject do
16
- builder = ChefProvisioningVsphere::CloneSpecBuilder.new(
17
- ChefProvisioningVsphereStubs::VsphereHelperStub.new,
18
- Chef::Provisioning::ActionHandler.new
19
- )
20
- builder.build(vm_template, 'machine_name', options)
21
- end
22
-
23
- context 'using linked clones' do
24
- before { options[:use_linked_clone] = true }
25
-
26
- it 'sets the disk move type of the relocation spec' do
27
- expect(subject.location.diskMoveType).to be :moveChildMostDiskBacking
28
- end
29
- end
30
-
31
- context 'using linked clone on a template source' do
32
- before do
33
- options[:use_linked_clone] = true
34
- options[:host] = 'host'
35
- allow(vm_template).to receive_message_chain(:config, :template)
36
- .and_return(true)
37
- end
38
-
39
- it 'does not set the disk move type of the relocation spec' do
40
- expect(subject.location.diskMoveType).to be nil
41
- end
42
- end
43
-
44
- context 'not using linked clones' do
45
- before { options[:use_linked_clone] = false }
46
-
47
- it 'does not set the disk move type of the relocation spec' do
48
- expect(subject.location.diskMoveType).to be nil
49
- end
50
- end
51
-
52
- context 'specifying a host' do
53
- before { options[:host] = 'host' }
54
-
55
- it 'sets the host' do
56
- expect(subject.location.host).to_not be nil
57
- end
58
- end
59
-
60
- context 'not specifying a host' do
61
- it 'does not set the host' do
62
- expect(subject.location.host).to be nil
63
- end
64
- end
65
-
66
- context 'specifying a pool' do
67
- before { options[:resource_pool] = 'pool' }
68
-
69
- it 'sets the pool' do
70
- expect(subject.location.pool).to_not be nil
71
- end
72
- end
73
-
74
- context 'not specifying a pool' do
75
- it 'does not set the pool' do
76
- expect(subject.location.pool).to be nil
77
- end
78
- end
79
-
80
- context 'not specifying a pool but specifying a host on a template' do
81
- before do
82
- options[:host] = 'host'
83
- allow(vm_template).to receive_message_chain(:config, :template)
84
- .and_return(true)
85
- end
86
-
87
- it 'sets the pool to the hosts parent root pool' do
88
- expect(subject.location.pool).to be subject.location.host.parent.resourcePool
89
- end
90
- end
91
-
92
- context 'not specifying a pool or host when cloning from a template' do
93
- before do
94
- allow(vm_template).to receive_message_chain(:config, :template)
95
- .and_return(true)
96
- end
97
-
98
- it 'raises an error' do
99
- expect { subject.to raise_error }
100
- end
101
- end
102
- end
@@ -1,52 +0,0 @@
1
- module ChefProvisioningVsphereStubs
2
- class VsphereHelperStub < ChefProvisioningVsphere::VsphereHelper
3
- def initialize
4
- end
5
-
6
- def network_device_changes(action_handler, vm_template, options)
7
- [
8
- [RbVmomi::VIM::VirtualDeviceConfigSpec.new],
9
- [RbVmomi::VIM::VirtualDeviceConfigSpec.new]
10
- ]
11
- end
12
-
13
- def find_host(host_name)
14
- RbVmomi::VIM::HostSystem.new
15
- end
16
-
17
- def find_pool(pool_name)
18
- RbVmomi::VIM::ResourcePool.new(nil, nil)
19
- end
20
-
21
- def find_datastore(datastore_name)
22
- RbVmomi::VIM::Datastore.new
23
- end
24
-
25
- def find_customization_spec(options)
26
- RbVmomi::VIM::CustomizationSpec.new
27
- end
28
-
29
- def create_delta_disk(vm_template)
30
- end
31
- end
32
- end
33
-
34
- module RbVmomi
35
- class VIM::HostSystem
36
- attr_reader :parent
37
-
38
- def parent
39
- @parent ||= RbVmomi::VIM::ComputeResource.new
40
- end
41
- end
42
- end
43
-
44
- module RbVmomi
45
- class VIM::ComputeResource
46
- attr_reader :resourcePool
47
-
48
- def resourcePool
49
- @resourcePool ||= RbVmomi::VIM::ResourcePool.new(nil, nil)
50
- end
51
- end
52
- end