chef-provisioning-vsphere 0.5.6 → 0.5.7.dev
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 +4 -4
- data/lib/chef/provisioning/vsphere_driver/clone_spec_builder.rb +190 -0
- data/lib/chef/provisioning/vsphere_driver/driver.rb +41 -14
- data/lib/chef/provisioning/vsphere_driver/version.rb +1 -1
- data/lib/chef/provisioning/vsphere_driver/vsphere_helpers.rb +18 -137
- data/spec/integration_tests/vsphere_driver_spec.rb +7 -6
- data/spec/unit_tests/clone_spec_builder_spec.rb +34 -0
- data/spec/unit_tests/support/vsphere_helper_stub.rb +32 -0
- metadata +9 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c95b01dfc2b3264c2e059c2c2251994e346ecdb9
|
|
4
|
+
data.tar.gz: 39fcb92ec638a6002688e89a75b4040648ebd009
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 295ea892e8aa73e61eb09cfd8e18663e01a2a6cd21cdf3bed5780c5de9a6a760730b61a18d7d286edf1bad39139461df9047f448f7c7492322a5ceb61f7a8eb0
|
|
7
|
+
data.tar.gz: 2a73a1f8c4308bcf701c915d849617eabc1011bed490fca7006da9e0ae4daca77b70d317b254304478612f02c8da53e61d3856e63354459daf4e7ed12d574f58
|
|
@@ -0,0 +1,190 @@
|
|
|
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
|
+
if options.has_key?(:host)
|
|
55
|
+
host = vsphere_helper.find_host(options[:host])
|
|
56
|
+
rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(host: host)
|
|
57
|
+
else
|
|
58
|
+
pool = vm_template.resourcePool
|
|
59
|
+
vpool = vsphere_helper.find_pool(options[:resource_pool])
|
|
60
|
+
rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(pool: vpool || pool)
|
|
61
|
+
raise "either :host or :resource_pool must be specified \
|
|
62
|
+
when cloning from a VM Template" if pool.nil?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
if options[:use_linked_clone]
|
|
66
|
+
vsphere_helper.create_delta_disk(vm_template)
|
|
67
|
+
rspec.diskMoveType = :moveChildMostDiskBacking
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
unless options[:datastore].to_s.empty?
|
|
71
|
+
rspec.datastore = vsphere_helper.find_datastore(options[:datastore])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
rspec
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def customization_options_from(vm_template, vm_name, options)
|
|
78
|
+
if options.has_key?(:customization_spec)
|
|
79
|
+
if(options[:customization_spec].is_a?(Hash))
|
|
80
|
+
cust_options = options[:customization_spec]
|
|
81
|
+
ip_settings = cust_options[:ipsettings]
|
|
82
|
+
cust_domain = cust_options[:domain]
|
|
83
|
+
|
|
84
|
+
raise ArgumentError, 'domain is required' unless cust_domain
|
|
85
|
+
cust_ip_settings = nil
|
|
86
|
+
if ip_settings && ip_settings.key?(:ip)
|
|
87
|
+
unless cust_options[:ipsettings].key?(:subnetMask)
|
|
88
|
+
raise ArgumentError, 'subnetMask is required for static ip'
|
|
89
|
+
end
|
|
90
|
+
cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(
|
|
91
|
+
ip_settings)
|
|
92
|
+
action_handler.report_progress "customizing #{vm_name} \
|
|
93
|
+
with static IP #{ip_settings[:ip]}"
|
|
94
|
+
cust_ip_settings.ip = RbVmomi::VIM::CustomizationFixedIp(
|
|
95
|
+
:ipAddress => ip_settings[:ip])
|
|
96
|
+
end
|
|
97
|
+
if cust_ip_settings.nil?
|
|
98
|
+
cust_ip_settings= RbVmomi::VIM::CustomizationIPSettings.new(
|
|
99
|
+
:ip => RbVmomi::VIM::CustomizationDhcpIpGenerator.new())
|
|
100
|
+
cust_ip_settings.dnsServerList = ip_settings[:dnsServerList]
|
|
101
|
+
action_handler.report_progress "customizing #{vm_name} with /
|
|
102
|
+
dynamic IP and DNS: #{ip_settings[:dnsServerList]}"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
cust_ip_settings.dnsDomain = cust_domain
|
|
106
|
+
global_ip_settings = RbVmomi::VIM::CustomizationGlobalIPSettings.new
|
|
107
|
+
global_ip_settings.dnsServerList = cust_ip_settings.dnsServerList
|
|
108
|
+
global_ip_settings.dnsSuffixList = [cust_domain]
|
|
109
|
+
cust_hostname = hostname_from(cust_options, vm_name)
|
|
110
|
+
cust_hwclockutc = cust_options[:hw_clock_utc]
|
|
111
|
+
cust_timezone = cust_options[:time_zone]
|
|
112
|
+
|
|
113
|
+
if vm_template.config.guestId.start_with?('win')
|
|
114
|
+
cust_prep = windows_prep_for(options, vm_name)
|
|
115
|
+
else
|
|
116
|
+
cust_prep = RbVmomi::VIM::CustomizationLinuxPrep.new(
|
|
117
|
+
:domain => cust_domain,
|
|
118
|
+
:hostName => cust_hostname,
|
|
119
|
+
:hwClockUTC => cust_hwclockutc,
|
|
120
|
+
:timeZone => cust_timezone
|
|
121
|
+
)
|
|
122
|
+
end
|
|
123
|
+
cust_adapter_mapping = [
|
|
124
|
+
RbVmomi::VIM::CustomizationAdapterMapping.new(
|
|
125
|
+
:adapter => cust_ip_settings)
|
|
126
|
+
]
|
|
127
|
+
RbVmomi::VIM::CustomizationSpec.new(
|
|
128
|
+
:identity => cust_prep,
|
|
129
|
+
:globalIPSettings => global_ip_settings,
|
|
130
|
+
:nicSettingMap => cust_adapter_mapping
|
|
131
|
+
)
|
|
132
|
+
else
|
|
133
|
+
vsphere_helper.find_customization_spec(cust_options)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def hostname_from(options, vm_name)
|
|
139
|
+
if options.key?(:hostname)
|
|
140
|
+
RbVmomi::VIM::CustomizationFixedName.new(:name => options[:hostname])
|
|
141
|
+
else
|
|
142
|
+
RbVmomi::VIM::CustomizationFixedName.new(:name => vm_name)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def windows_prep_for(options, vm_name)
|
|
147
|
+
cust_options = options[:customization_spec]
|
|
148
|
+
cust_runonce = RbVmomi::VIM::CustomizationGuiRunOnce.new(
|
|
149
|
+
:commandList => [
|
|
150
|
+
'winrm set winrm/config/client/auth @{Basic="true"}',
|
|
151
|
+
'winrm set winrm/config/service/auth @{Basic="true"}',
|
|
152
|
+
'winrm set winrm/config/service @{AllowUnencrypted="true"}',
|
|
153
|
+
'shutdown -l'])
|
|
154
|
+
|
|
155
|
+
cust_login_password = RbVmomi::VIM::CustomizationPassword(
|
|
156
|
+
:plainText => true,
|
|
157
|
+
:value => options[:ssh][:password])
|
|
158
|
+
if cust_options.has_key?(:domain) and cust_options[:domain] != 'local'
|
|
159
|
+
cust_domain_password = RbVmomi::VIM::CustomizationPassword(
|
|
160
|
+
:plainText => true,
|
|
161
|
+
:value => ENV['domainAdminPassword'] || cust_options[:domainAdminPassword])
|
|
162
|
+
cust_id = RbVmomi::VIM::CustomizationIdentification.new(
|
|
163
|
+
:joinDomain => cust_options[:domain],
|
|
164
|
+
:domainAdmin => cust_options[:domainAdmin],
|
|
165
|
+
:domainAdminPassword => cust_domain_password)
|
|
166
|
+
#puts "my env passwd is: #{ENV['domainAdminPassword']}"
|
|
167
|
+
action_handler.report_progress "joining domain #{cust_options[:domain]} /
|
|
168
|
+
with user: #{cust_options[:domainAdmin]}"
|
|
169
|
+
else
|
|
170
|
+
cust_id = RbVmomi::VIM::CustomizationIdentification.new(
|
|
171
|
+
:joinWorkgroup => 'WORKGROUP')
|
|
172
|
+
end
|
|
173
|
+
cust_gui_unattended = RbVmomi::VIM::CustomizationGuiUnattended.new(
|
|
174
|
+
:autoLogon => true,
|
|
175
|
+
:autoLogonCount => 1,
|
|
176
|
+
:password => cust_login_password,
|
|
177
|
+
:timeZone => cust_options[:win_time_zone])
|
|
178
|
+
cust_userdata = RbVmomi::VIM::CustomizationUserData.new(
|
|
179
|
+
:computerName => hostname_from(cust_options, vm_name),
|
|
180
|
+
:fullName => cust_options[:org_name],
|
|
181
|
+
:orgName => cust_options[:org_name],
|
|
182
|
+
:productId => cust_options[:product_id])
|
|
183
|
+
RbVmomi::VIM::CustomizationSysprep.new(
|
|
184
|
+
:guiRunOnce => cust_runonce,
|
|
185
|
+
:identification => cust_id,
|
|
186
|
+
:guiUnattended => cust_gui_unattended,
|
|
187
|
+
:userData => cust_userdata)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
@@ -3,6 +3,7 @@ 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'
|
|
6
7
|
require 'chef/provisioning/vsphere_driver/version'
|
|
7
8
|
require 'chef/provisioning/vsphere_driver/vsphere_helpers'
|
|
8
9
|
require 'chef/provisioning/vsphere_driver/vsphere_url'
|
|
@@ -11,7 +12,6 @@ module ChefProvisioningVsphere
|
|
|
11
12
|
# Provisions machines in vSphere.
|
|
12
13
|
class VsphereDriver < Chef::Provisioning::Driver
|
|
13
14
|
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 = find_vm(
|
|
166
|
+
vm = vsphere_helper.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 = add_extra_nic(
|
|
234
|
+
new_nics = vsphere_helper.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
|
-
start_vm(vm)
|
|
316
|
+
vsphere_helper.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
|
-
stop_vm(vm)
|
|
398
|
+
vsphere_helper.stop_vm(vm)
|
|
399
399
|
end
|
|
400
400
|
end
|
|
401
401
|
end
|
|
@@ -405,14 +405,14 @@ 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
|
-
start_vm(vm, machine_options[:bootstrap_options][:ssh][:port])
|
|
408
|
+
vsphere_helper.start_vm(vm, machine_options[:bootstrap_options][:ssh][:port])
|
|
409
409
|
end
|
|
410
410
|
end
|
|
411
411
|
vm
|
|
412
412
|
end
|
|
413
413
|
|
|
414
414
|
def restart_server(action_handler, machine_spec, machine_options)
|
|
415
|
-
action_handler.perform_action "restart machine #{machine_spec.name} (#{
|
|
415
|
+
action_handler.perform_action "restart machine #{machine_spec.name} (#{driver_url})" do
|
|
416
416
|
stop_machine(action_handler, machine_spec, machine_options)
|
|
417
417
|
start_machine(action_handler, machine_spec, machine_options)
|
|
418
418
|
machine_spec.location['started_at'] = Time.now.utc.to_s
|
|
@@ -484,25 +484,52 @@ module ChefProvisioningVsphere
|
|
|
484
484
|
|
|
485
485
|
def vm_for(machine_spec)
|
|
486
486
|
if machine_spec.location
|
|
487
|
-
find_vm_by_id(machine_spec.location['server_id'])
|
|
487
|
+
vsphere_helper.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
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
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
|
+
|
|
499
|
+
vm_folder = vsphere_helper.find_folder(bootstrap_options[:vm_folder])
|
|
500
|
+
vm_template.CloneVM_Task(
|
|
501
|
+
name: machine_name,
|
|
502
|
+
folder: vm_folder,
|
|
503
|
+
spec: clone_spec
|
|
504
|
+
).wait_for_completion
|
|
505
|
+
|
|
506
|
+
vm = vsphere_helper.find_vm(vm_folder, machine_name)
|
|
507
|
+
|
|
508
|
+
if bootstrap_options[:additional_disk_size_gb].to_i > 0
|
|
509
|
+
task = vm.ReconfigVM_Task(
|
|
510
|
+
spec: RbVmomi::VIM.VirtualMachineConfigSpec(
|
|
511
|
+
deviceChange: [
|
|
512
|
+
vsphere_helper.virtual_disk_for(vm, bootstrap_options)
|
|
513
|
+
]
|
|
514
|
+
)
|
|
515
|
+
)
|
|
516
|
+
task.wait_for_completion
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
vm
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
def vsphere_helper
|
|
523
|
+
@vsphere_helper ||= VsphereHelper.new(
|
|
524
|
+
connect_options,
|
|
525
|
+
config[:machine_options][:bootstrap_options][:datacenter]
|
|
499
526
|
)
|
|
500
527
|
end
|
|
501
528
|
|
|
502
529
|
def vm_template_for(bootstrap_options)
|
|
503
530
|
template_folder = bootstrap_options[:template_folder]
|
|
504
531
|
template_name = bootstrap_options[:template_name]
|
|
505
|
-
find_vm(template_folder, template_name) ||
|
|
532
|
+
vsphere_helper.find_vm(template_folder, template_name) ||
|
|
506
533
|
raise("vSphere VM Template not found [#{template_folder}/#{template_name}]")
|
|
507
534
|
end
|
|
508
535
|
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
require 'rbvmomi'
|
|
2
2
|
|
|
3
3
|
module ChefProvisioningVsphere
|
|
4
|
-
|
|
4
|
+
class VsphereHelper
|
|
5
5
|
|
|
6
6
|
if !$guest_op_managers
|
|
7
7
|
$guest_op_managers = {}
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def
|
|
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
|
|
11
19
|
if @current_connection.nil? or @current_connection.serviceContent.sessionManager.currentSession.nil?
|
|
12
|
-
puts "establishing connection to #{
|
|
13
|
-
@current_connection = RbVmomi::VIM.connect
|
|
20
|
+
puts "establishing connection to #{connect_options[:host]}"
|
|
21
|
+
@current_connection = RbVmomi::VIM.connect connect_options
|
|
14
22
|
str_conn = @current_connection.pretty_inspect # a string in the format of VIM(host ip)
|
|
15
23
|
|
|
16
24
|
# we are caching guest operation managers in a global variable...terrible i know
|
|
@@ -31,8 +39,8 @@ module ChefProvisioningVsphere
|
|
|
31
39
|
folder.find(vm_name, RbVmomi::VIM::VirtualMachine)
|
|
32
40
|
end
|
|
33
41
|
|
|
34
|
-
def find_vm_by_id(uuid
|
|
35
|
-
vm =
|
|
42
|
+
def find_vm_by_id(uuid)
|
|
43
|
+
vm = vim.searchIndex.FindByUuid(
|
|
36
44
|
uuid: uuid,
|
|
37
45
|
vmSearch: true,
|
|
38
46
|
instanceUuid: true
|
|
@@ -108,9 +116,8 @@ module ChefProvisioningVsphere
|
|
|
108
116
|
end
|
|
109
117
|
|
|
110
118
|
def datacenter
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
raise("vSphere Datacenter not found [#{dc_name}]")
|
|
119
|
+
@datacenter ||= vim.serviceInstance.find_datacenter(datacenter_name) ||
|
|
120
|
+
raise("vSphere Datacenter not found [#{datacenter_name}]")
|
|
114
121
|
end
|
|
115
122
|
|
|
116
123
|
def network_adapter_for(operation, network_name, network_label, device_key, backing_info)
|
|
@@ -206,28 +213,6 @@ module ChefProvisioningVsphere
|
|
|
206
213
|
end
|
|
207
214
|
end
|
|
208
215
|
|
|
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
|
-
|
|
231
216
|
def create_delta_disk(vm_template)
|
|
232
217
|
disks = vm_template.config.hardware.device.grep(RbVmomi::VIM::VirtualDisk)
|
|
233
218
|
disks.select { |disk| disk.backing.parent == nil }.each do |disk|
|
|
@@ -326,110 +311,6 @@ module ChefProvisioningVsphere
|
|
|
326
311
|
datacenter.datastore.find { |f| f.info.name == datastore_name } or raise "no such datastore #{datastore_name}"
|
|
327
312
|
end
|
|
328
313
|
|
|
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
|
-
|
|
433
314
|
def find_entity(name, parent_folder, &block)
|
|
434
315
|
parts = name.split('/').reject(&:empty?)
|
|
435
316
|
parts.each do |item|
|
|
@@ -456,8 +337,8 @@ module ChefProvisioningVsphere
|
|
|
456
337
|
|
|
457
338
|
raise "vSphere Host not found [#{host_name}]" if host.nil?
|
|
458
339
|
|
|
459
|
-
if
|
|
460
|
-
host = host.
|
|
340
|
+
if host.is_a?(RbVmomi::VIM::ComputeResource)
|
|
341
|
+
host = host.first
|
|
461
342
|
end
|
|
462
343
|
host
|
|
463
344
|
end
|
|
@@ -34,8 +34,6 @@ require 'chef/provisioning/machine_spec'
|
|
|
34
34
|
# }
|
|
35
35
|
|
|
36
36
|
describe 'vsphere_driver' do
|
|
37
|
-
include ChefProvisioningVsphere::Helpers
|
|
38
|
-
|
|
39
37
|
before :all do
|
|
40
38
|
@vm_name = "cmvd-test-#{SecureRandom.hex}"
|
|
41
39
|
@metal_config = eval File.read(File.expand_path('../config.rb', __FILE__))
|
|
@@ -49,8 +47,11 @@ describe 'vsphere_driver' do
|
|
|
49
47
|
@metal_config[:machine_options][:convergence_options] = {:chef_server => chef_server}
|
|
50
48
|
machine = @driver.ready_machine(action_handler, @machine_spec, @metal_config[:machine_options])
|
|
51
49
|
@server_id = @machine_spec.location['server_id']
|
|
52
|
-
@
|
|
53
|
-
|
|
50
|
+
@vsphere_helper = ChefProvisioningVsphere::VsphereHelper.new(
|
|
51
|
+
@metal_config[:driver_options],
|
|
52
|
+
@metal_config[:machine_options][:bootstrap_options][:datacenter]
|
|
53
|
+
)
|
|
54
|
+
@vm = @vsphere_helper.find_vm_by_id(@server_id)
|
|
54
55
|
end
|
|
55
56
|
end
|
|
56
57
|
|
|
@@ -101,7 +102,7 @@ describe 'vsphere_driver' do
|
|
|
101
102
|
end
|
|
102
103
|
end
|
|
103
104
|
it 'is in the correct datacenter' do
|
|
104
|
-
expect(@
|
|
105
|
+
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)
|
|
105
106
|
end
|
|
106
107
|
it 'has an added disk of the correct size' do
|
|
107
108
|
disk_count = @vm.disks.count
|
|
@@ -146,7 +147,7 @@ describe 'vsphere_driver' do
|
|
|
146
147
|
@metal_config[:machine_options]
|
|
147
148
|
)
|
|
148
149
|
end
|
|
149
|
-
vm = find_vm_by_id(@server_id
|
|
150
|
+
vm = @vsphere_helper.find_vm_by_id(@server_id)
|
|
150
151
|
expect(vm).to eq(nil)
|
|
151
152
|
end
|
|
152
153
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
require 'chef/provisioning/vsphere_driver'
|
|
2
|
+
|
|
3
|
+
require_relative 'support/vsphere_helper_stub'
|
|
4
|
+
|
|
5
|
+
describe ChefProvisioningVsphere::CloneSpecBuilder do
|
|
6
|
+
let(:options) { { host: 'host' } }
|
|
7
|
+
let(:vm_template) { double('template', resourcePool: 'pool') }
|
|
8
|
+
|
|
9
|
+
before { allow(vm_template).to receive_message_chain(:config, :guestId) }
|
|
10
|
+
|
|
11
|
+
subject do
|
|
12
|
+
builder = ChefProvisioningVsphere::CloneSpecBuilder.new(
|
|
13
|
+
ChefProvisioningVsphereStubs::VsphereHelperStub.new,
|
|
14
|
+
Chef::Provisioning::ActionHandler.new
|
|
15
|
+
)
|
|
16
|
+
builder.build(vm_template, 'machine_name', options)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
context 'using linked clones' do
|
|
20
|
+
before { options[:use_linked_clone] = true }
|
|
21
|
+
|
|
22
|
+
it 'sets the disk move type of the relocation spec' do
|
|
23
|
+
expect(subject.location.diskMoveType).to be :moveChildMostDiskBacking
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
context 'not using linked clones' do
|
|
28
|
+
before { options[:use_linked_clone] = false }
|
|
29
|
+
|
|
30
|
+
it 'sets the disk move type of the relocation spec' do
|
|
31
|
+
expect(subject.location.diskMoveType).to be nil
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
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(nil, nil)
|
|
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
|
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.
|
|
4
|
+
version: 0.5.7.dev
|
|
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-
|
|
11
|
+
date: 2015-06-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rbvmomi
|
|
@@ -103,6 +103,7 @@ 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
|
|
106
107
|
- lib/chef/provisioning/vsphere_driver/driver.rb
|
|
107
108
|
- lib/chef/provisioning/vsphere_driver/version.rb
|
|
108
109
|
- lib/chef/provisioning/vsphere_driver/vsphere_helpers.rb
|
|
@@ -112,6 +113,8 @@ files:
|
|
|
112
113
|
- spec/integration_tests/vsphere_driver_spec.rb
|
|
113
114
|
- spec/unit_tests/VsphereDriver_spec.rb
|
|
114
115
|
- spec/unit_tests/VsphereUrl_spec.rb
|
|
116
|
+
- spec/unit_tests/clone_spec_builder_spec.rb
|
|
117
|
+
- spec/unit_tests/support/vsphere_helper_stub.rb
|
|
115
118
|
homepage: https://github.com/tier3/chef-provisioning-vsphere
|
|
116
119
|
licenses:
|
|
117
120
|
- MIT
|
|
@@ -127,9 +130,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
127
130
|
version: '0'
|
|
128
131
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
132
|
requirements:
|
|
130
|
-
- - "
|
|
133
|
+
- - ">"
|
|
131
134
|
- !ruby/object:Gem::Version
|
|
132
|
-
version:
|
|
135
|
+
version: 1.3.1
|
|
133
136
|
requirements: []
|
|
134
137
|
rubyforge_project:
|
|
135
138
|
rubygems_version: 2.4.4
|
|
@@ -141,4 +144,6 @@ test_files:
|
|
|
141
144
|
- spec/integration_tests/vsphere_driver_spec.rb
|
|
142
145
|
- spec/unit_tests/VsphereDriver_spec.rb
|
|
143
146
|
- spec/unit_tests/VsphereUrl_spec.rb
|
|
147
|
+
- spec/unit_tests/clone_spec_builder_spec.rb
|
|
148
|
+
- spec/unit_tests/support/vsphere_helper_stub.rb
|
|
144
149
|
has_rdoc:
|