chef-provisioning-vsphere 0.4.2 → 0.5.0
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/Gemfile +1 -1
- data/LICENSE +20 -0
- data/chef-provisioning-vsphere.gemspec +1 -1
- data/lib/chef/provisioning/vsphere_driver.rb +4 -3
- data/lib/chef/provisioning/vsphere_driver/driver.rb +288 -212
- data/lib/chef/provisioning/vsphere_driver/version.rb +1 -1
- data/lib/chef/provisioning/vsphere_driver/vsphere_url.rb +39 -25
- data/spec/integration_tests/vsphere_driver_spec.rb +135 -133
- data/spec/unit_tests/VsphereDriver_spec.rb +163 -203
- data/spec/unit_tests/VsphereUrl_spec.rb +7 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 990036a8b6dcc42e111ed4acb92aa90c5fe59f1d
|
4
|
+
data.tar.gz: 2767a8e7fd769b90954e57b06eecccfa0fd29736
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0784aeb6843b433d16f5aa93aee499e55ed0aad8b2dd6b8c6378258d9c504ac78fcac3d6cf7e4abdda19e580b6c58ce8a58853db7d2342ab38a943f51e91329c
|
7
|
+
data.tar.gz: e68182faff627baf71b3b0074cc14fac995908123f0bcdef2e263b70cd147496a40fb299b7d9797fd31da826f37176bc7ab9781bd6fb8a2b045a913b6742f0b2
|
data/Gemfile
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2015 CenturyLink
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.authors = ['CenturyLink Cloud']
|
12
12
|
s.email = 'matt.wrock@CenturyLinkCloud.com'
|
13
13
|
s.homepage = 'https://github.com/tier3/chef-provisioning-vsphere'
|
14
|
-
s.license = '
|
14
|
+
s.license = 'MIT'
|
15
15
|
|
16
16
|
s.bindir = 'bin'
|
17
17
|
s.executables = %w( )
|
@@ -5,9 +5,10 @@ class Chef
|
|
5
5
|
module DSL
|
6
6
|
module Recipe
|
7
7
|
def with_vsphere_driver(driver_options, &block)
|
8
|
-
|
9
|
-
|
8
|
+
url = ChefProvisioningVsphere::VsphereDriver.canonicalize_url(
|
9
|
+
nil, driver_options)[0]
|
10
|
+
with_driver url, driver_options, &block
|
10
11
|
end
|
11
12
|
end
|
12
13
|
end
|
13
|
-
end
|
14
|
+
end
|
@@ -17,51 +17,20 @@ module ChefProvisioningVsphere
|
|
17
17
|
VsphereDriver.new(driver_url, config)
|
18
18
|
end
|
19
19
|
|
20
|
+
# Create a new Vsphere provisioner.
|
21
|
+
#
|
22
|
+
# ## Parameters
|
23
|
+
# connect_options - hash of options to be passed to RbVmomi::VIM.connect
|
24
|
+
# :host - required - hostname of the vSphere API server
|
25
|
+
# :port - optional - port on the vSphere API server (default: 443)
|
26
|
+
# :path - optional - path on the vSphere API server (default: /sdk)
|
27
|
+
# :use_ssl - optional - true to use ssl in connection to vSphere API server (default: true)
|
28
|
+
# :insecure - optional - true to ignore ssl certificate validation errors in connection to vSphere API server (default: false)
|
29
|
+
# :user - required - user name to use in connection to vSphere API server
|
30
|
+
# :password - required - password to use in connection to vSphere API server
|
20
31
|
def self.canonicalize_url(driver_url, config)
|
21
32
|
config = symbolize_keys(config)
|
22
|
-
|
23
|
-
:driver_options => { :connect_options => { :port => 443,
|
24
|
-
:use_ssl => true,
|
25
|
-
:insecure => false,
|
26
|
-
:path => '/sdk'
|
27
|
-
} },
|
28
|
-
:machine_options => { :start_timeout => 600,
|
29
|
-
:create_timeout => 600,
|
30
|
-
:ready_timeout => 300,
|
31
|
-
:bootstrap_options => { :ssh => { :port => 22,
|
32
|
-
:user => 'root' },
|
33
|
-
:key_name => 'metal_default',
|
34
|
-
:tags => {} } }
|
35
|
-
}
|
36
|
-
|
37
|
-
new_connect_options = {}
|
38
|
-
new_connect_options[:provider] = 'vsphere'
|
39
|
-
if !driver_url.nil?
|
40
|
-
uri = URI(driver_url)
|
41
|
-
new_connect_options[:host] = uri.host
|
42
|
-
new_connect_options[:port] = uri.port
|
43
|
-
if uri.path && uri.path.length > 0
|
44
|
-
new_connect_options[:path] = uri.path
|
45
|
-
end
|
46
|
-
new_connect_options[:use_ssl] = uri.use_ssl
|
47
|
-
new_connect_options[:insecure] = uri.insecure
|
48
|
-
end
|
49
|
-
new_connect_options = new_connect_options.merge(config[:driver_options])
|
50
|
-
|
51
|
-
new_config = { :driver_options => { :connect_options => new_connect_options }}
|
52
|
-
config = Cheffish::MergedConfig.new(new_config, config, new_defaults)
|
53
|
-
|
54
|
-
required_options = [:host, :user, :password]
|
55
|
-
missing_options = []
|
56
|
-
required_options.each do |opt|
|
57
|
-
missing_options << opt unless config[:driver_options][:connect_options].has_key?(opt)
|
58
|
-
end
|
59
|
-
unless missing_options.empty?
|
60
|
-
raise "missing required options: #{missing_options.join(', ')}"
|
61
|
-
end
|
62
|
-
|
63
|
-
url = URI::VsphereUrl.from_config(config[:driver_options][:connect_options]).to_s
|
64
|
-
[ url, config ]
|
33
|
+
[ driver_url || URI::VsphereUrl.from_config(config).to_s, config ]
|
65
34
|
end
|
66
35
|
|
67
36
|
def self.symbolize_keys(h)
|
@@ -73,22 +42,23 @@ module ChefProvisioningVsphere
|
|
73
42
|
] : h
|
74
43
|
end
|
75
44
|
|
76
|
-
# Create a new Vsphere provisioner.
|
77
|
-
#
|
78
|
-
# ## Parameters
|
79
|
-
# connect_options - hash of options to be passed to RbVmomi::VIM.connect
|
80
|
-
# :host - required - hostname of the vSphere API server
|
81
|
-
# :port - optional - port on the vSphere API server (default: 443)
|
82
|
-
# :path - optional - path on the vSphere API server (default: /sdk)
|
83
|
-
# :use_ssl - optional - true to use ssl in connection to vSphere API server (default: true)
|
84
|
-
# :insecure - optional - true to ignore ssl certificate validation errors in connection to vSphere API server (default: false)
|
85
|
-
# :user - required - user name to use in connection to vSphere API server
|
86
|
-
# :password - required - password to use in connection to vSphere API server
|
87
|
-
# :proxy_host - optional - http proxy host to use in connection to vSphere API server (default: none)
|
88
|
-
# :proxy_port - optional - http proxy port to use in connection to vSphere API server (default: none)
|
89
45
|
def initialize(driver_url, config)
|
90
46
|
super(driver_url, config)
|
91
|
-
|
47
|
+
|
48
|
+
uri = URI(driver_url)
|
49
|
+
@connect_options = {
|
50
|
+
provider: 'vsphere',
|
51
|
+
host: uri.host,
|
52
|
+
port: uri.port,
|
53
|
+
use_ssl: uri.use_ssl,
|
54
|
+
insecure: uri.insecure,
|
55
|
+
path: uri.path
|
56
|
+
}
|
57
|
+
|
58
|
+
if driver_options
|
59
|
+
@connect_options[:user] = driver_options[:user]
|
60
|
+
@connect_options[:password] = driver_options[:password]
|
61
|
+
end
|
92
62
|
end
|
93
63
|
|
94
64
|
attr_reader :connect_options
|
@@ -141,38 +111,38 @@ module ChefProvisioningVsphere
|
|
141
111
|
#
|
142
112
|
def allocate_machine(action_handler, machine_spec, machine_options)
|
143
113
|
if machine_spec.location
|
144
|
-
Chef::Log.warn
|
114
|
+
Chef::Log.warn(
|
115
|
+
"Checking to see if #{machine_spec.location} has been created...")
|
145
116
|
vm = vm_for(machine_spec)
|
146
117
|
if vm
|
147
|
-
Chef::Log.warn
|
118
|
+
Chef::Log.warn 'returning existing machine'
|
148
119
|
return vm
|
149
120
|
else
|
150
|
-
Chef::Log.warn
|
121
|
+
Chef::Log.warn machine_msg(
|
122
|
+
machine_spec.name,
|
123
|
+
machine_spec.location['server_id'],
|
124
|
+
'no longer exists. Recreating ...'
|
125
|
+
)
|
151
126
|
end
|
152
127
|
end
|
153
|
-
bootstrap_options =
|
154
|
-
vm = nil
|
128
|
+
bootstrap_options = machine_options[:bootstrap_options]
|
155
129
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
raise 'bootstrapping is currently supported for ssh only'
|
161
|
-
# wait_on_port = bootstrap_options['winrm']['port']
|
162
|
-
end
|
130
|
+
action_handler.report_progress full_description(
|
131
|
+
machine_spec, bootstrap_options)
|
132
|
+
|
133
|
+
vm = find_or_create_vm(bootstrap_options, machine_spec, action_handler)
|
163
134
|
|
164
|
-
|
165
|
-
bootstrap_options.each_pair { |key,value| description << " #{key}: #{value.inspect}" }
|
166
|
-
action_handler.report_progress description
|
135
|
+
add_machine_spec_location(vm, machine_spec)
|
167
136
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
137
|
+
action_handler.performed_action(machine_msg(
|
138
|
+
machine_spec.name,
|
139
|
+
vm.config.instanceUuid,
|
140
|
+
'created'
|
141
|
+
))
|
142
|
+
vm
|
143
|
+
end
|
175
144
|
|
145
|
+
def add_machine_spec_location(vm, machine_spec)
|
176
146
|
machine_spec.location = {
|
177
147
|
'driver_url' => driver_url,
|
178
148
|
'driver_version' => VERSION,
|
@@ -181,100 +151,199 @@ module ChefProvisioningVsphere
|
|
181
151
|
'allocated_at' => Time.now.utc.to_s,
|
182
152
|
'ipaddress' => vm.guest.ipAddress
|
183
153
|
}
|
184
|
-
|
185
|
-
%w(ssh_username sudo use_private_ip_for_ssh ssh_gateway).each do |key|
|
186
|
-
machine_spec.location[key] = machine_options[key.to_sym] if machine_options[key.to_sym]
|
187
|
-
end
|
154
|
+
end
|
188
155
|
|
189
|
-
|
156
|
+
def find_or_create_vm(bootstrap_options, machine_spec, action_handler)
|
157
|
+
vm = find_vm(
|
158
|
+
bootstrap_options[:datacenter],
|
159
|
+
bootstrap_options[:vm_folder],
|
160
|
+
machine_spec.name
|
161
|
+
)
|
162
|
+
server_id = nil
|
163
|
+
if vm
|
164
|
+
Chef::Log.info machine_msg(
|
165
|
+
machine_spec.name,
|
166
|
+
vm.config.instanceUuid,
|
167
|
+
'already created'
|
168
|
+
)
|
169
|
+
else
|
170
|
+
vm = clone_vm(action_handler, bootstrap_options, machine_spec.name)
|
171
|
+
end
|
190
172
|
vm
|
191
173
|
end
|
192
174
|
|
175
|
+
def full_description(machine_spec, bootstrap_options)
|
176
|
+
description = [ "creating machine #{machine_spec.name} on #{driver_url}" ]
|
177
|
+
bootstrap_options.to_hash.each_pair do |key,value|
|
178
|
+
description << " #{key}: #{value.inspect}"
|
179
|
+
end
|
180
|
+
description
|
181
|
+
end
|
182
|
+
|
183
|
+
def machine_msg(name, id, action)
|
184
|
+
"Machine - #{action} - #{name} (#{id} on #{driver_url})"
|
185
|
+
end
|
186
|
+
|
193
187
|
def ready_machine(action_handler, machine_spec, machine_options)
|
194
188
|
start_machine(action_handler, machine_spec, machine_options)
|
195
189
|
vm = vm_for(machine_spec)
|
196
190
|
if vm.nil?
|
197
|
-
raise "Machine #{machine_spec.name} does not have a server
|
191
|
+
raise "Machine #{machine_spec.name} does not have a server "\
|
192
|
+
'associated with it, or server does not exist.'
|
198
193
|
end
|
199
194
|
|
200
|
-
|
195
|
+
bootstrap_options = machine_options[:bootstrap_options]
|
201
196
|
|
202
|
-
|
197
|
+
transport_respond?(
|
198
|
+
machine_options,
|
199
|
+
vm,
|
200
|
+
action_handler,
|
201
|
+
machine_spec
|
202
|
+
)
|
203
203
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
204
|
+
machine = machine_for(machine_spec,machine_options)
|
205
|
+
setup_extra_nics(action_handler, bootstrap_options, vm, machine)
|
206
|
+
|
207
|
+
if has_static_ip(bootstrap_options) && !is_windows?(vm)
|
208
|
+
setup_ubuntu_dns(machine, bootstrap_options, machine_spec)
|
208
209
|
end
|
209
210
|
|
210
|
-
|
211
|
-
|
212
|
-
now = Time.now.utc
|
211
|
+
machine
|
212
|
+
end
|
213
213
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
end
|
227
|
-
now = Time.now.utc
|
228
|
-
until (Time.now.utc - now) > 90 || (vm.guest.net.map { |net| net.ipAddress}.flatten).include?(vm_ip) do
|
229
|
-
vm_ip = ip_for(bootstrap_options, vm) if vm_ip.nil?
|
230
|
-
print "-"
|
231
|
-
sleep 5
|
232
|
-
end
|
214
|
+
def setup_extra_nics(action_handler, bootstrap_options, vm, machine)
|
215
|
+
new_nics = add_extra_nic(
|
216
|
+
action_handler,
|
217
|
+
vm_template_for(bootstrap_options),
|
218
|
+
bootstrap_options,
|
219
|
+
vm
|
220
|
+
)
|
221
|
+
if is_windows?(vm) && !new_nics.nil?
|
222
|
+
new_nics.each do |nic|
|
223
|
+
nic_label = nic.device.deviceInfo.label
|
224
|
+
machine.execute_always(
|
225
|
+
"Disable-Netadapter -Name '#{nic_label}' -Confirm:$false")
|
233
226
|
end
|
234
|
-
machine_spec.location['ipaddress'] = vm.guest.ipAddress
|
235
|
-
action_handler.report_progress "IP address obtained: #{machine_spec.location['ipaddress']}"
|
236
227
|
end
|
228
|
+
end
|
237
229
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
230
|
+
def transport_respond?(
|
231
|
+
machine_options,
|
232
|
+
vm,
|
233
|
+
action_handler,
|
234
|
+
machine_spec
|
235
|
+
)
|
236
|
+
bootstrap_options = machine_options[:bootstrap_options]
|
237
|
+
|
238
|
+
# this waits for vmware tools to start and the vm to presebnt an ip
|
239
|
+
# This may just be the ip of a newly cloned machine
|
240
|
+
# Customization below may change this to a valid ip
|
241
|
+
wait_until_ready(action_handler, machine_spec, machine_options, vm)
|
242
|
+
|
243
|
+
# find the ip we actually want
|
244
|
+
# this will be the static ip to assign
|
245
|
+
# or the ip reported back by the vm if using dhcp
|
246
|
+
# it *may* be nil if just cloned
|
247
|
+
vm_ip = ip_to_bootstrap(bootstrap_options, vm)
|
248
|
+
transport = nil
|
249
|
+
unless vm_ip.nil?
|
250
|
+
transport = transport_for(machine_spec, bootstrap_options[:ssh], vm_ip)
|
251
|
+
end
|
252
|
+
|
253
|
+
unless !transport.nil? && transport.available? && has_ip?(vm_ip, vm)
|
254
|
+
attempt_ip(machine_options, action_handler, vm, machine_spec)
|
248
255
|
end
|
256
|
+
machine_spec.location['ipaddress'] = vm.guest.ipAddress
|
257
|
+
action_handler.report_progress(
|
258
|
+
"IP address obtained: #{machine_spec.location['ipaddress']}")
|
259
|
+
|
260
|
+
wait_for_domain(bootstrap_options, vm, machine_spec, action_handler)
|
249
261
|
|
250
262
|
begin
|
251
263
|
wait_for_transport(action_handler, machine_spec, machine_options, vm)
|
252
264
|
rescue Timeout::Error
|
253
|
-
# Only ever reboot once, and only if it's been less than 10 minutes
|
254
|
-
|
265
|
+
# Only ever reboot once, and only if it's been less than 10 minutes
|
266
|
+
# since we stopped waiting
|
267
|
+
if machine_spec.location['started_at'] ||
|
268
|
+
remaining_wait_time(machine_spec, machine_options) < -(10*60)
|
255
269
|
raise
|
256
270
|
else
|
257
|
-
Chef::Log.warn
|
271
|
+
Chef::Log.warn(machine_msg(
|
272
|
+
machine_spec.name,
|
273
|
+
vm.config.instanceUuid,
|
274
|
+
'started but SSH did not come up. Rebooting...'
|
275
|
+
))
|
258
276
|
restart_server(action_handler, machine_spec, vm)
|
259
277
|
wait_until_ready(action_handler, machine_spec, machine_options, vm)
|
260
278
|
wait_for_transport(action_handler, machine_spec, machine_options, vm)
|
261
279
|
end
|
262
280
|
end
|
281
|
+
end
|
263
282
|
|
264
|
-
|
283
|
+
def attempt_ip(machine_options, action_handler, vm, machine_spec)
|
284
|
+
vm_ip = ip_to_bootstrap(machine_options[:bootstrap_options], vm)
|
285
|
+
|
286
|
+
wait_for_ip(vm, machine_options, action_handler)
|
287
|
+
|
288
|
+
unless has_ip?(vm_ip, vm)
|
289
|
+
action_handler.report_progress "rebooting..."
|
290
|
+
if vm.guest.toolsRunningStatus != "guestToolsRunning"
|
291
|
+
msg = 'tools have stopped. current power state is '
|
292
|
+
msg << vm.runtime.powerState
|
293
|
+
msg << ' and tools state is '
|
294
|
+
msg << vm.guest.toolsRunningStatus
|
295
|
+
msg << '. powering up server...'
|
296
|
+
action_handler.report_progress(msg.join)
|
297
|
+
start_vm(vm)
|
298
|
+
else
|
299
|
+
restart_server(action_handler, machine_spec, vm)
|
300
|
+
end
|
301
|
+
wait_for_ip(vm, machine_options, action_handler)
|
302
|
+
end
|
303
|
+
end
|
265
304
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
305
|
+
def wait_for_domain(bootstrap_options, vm, machine_spec, action_handler)
|
306
|
+
return unless bootstrap_options[:customization_spec]
|
307
|
+
return unless bootstrap_options[:customization_spec][:domain]
|
308
|
+
|
309
|
+
domain = bootstrap_options[:customization_spec][:domain]
|
310
|
+
if is_windows?(vm) && domain != 'local'
|
311
|
+
start = Time.now.utc
|
312
|
+
trimmed_name = machine_spec.name.byteslice(0,15)
|
313
|
+
expected_name="#{trimmed_name}.#{domain}"
|
314
|
+
action_handler.report_progress(
|
315
|
+
"waiting to domain join and be named #{expected_name}")
|
316
|
+
until (Time.now.utc - start) > 30 ||
|
317
|
+
(vm.guest.hostName == expected_name) do
|
318
|
+
print '.'
|
319
|
+
sleep 5
|
270
320
|
end
|
271
321
|
end
|
322
|
+
end
|
272
323
|
|
273
|
-
|
274
|
-
|
324
|
+
def wait_for_ip(vm, machine_options, action_handler)
|
325
|
+
bootstrap_options = machine_options[:bootstrap_options]
|
326
|
+
vm_ip = ip_to_bootstrap(bootstrap_options, vm)
|
327
|
+
ready_timeout = machine_options[:ready_timeout] || 300
|
328
|
+
msg = "waiting up to #{ready_timeout} seconds for customization"
|
329
|
+
msg << " and find #{vm_ip}" unless vm_ip == vm.guest.ipAddress
|
330
|
+
action_handler.report_progress msg
|
331
|
+
|
332
|
+
start = Time.now.utc
|
333
|
+
until (Time.now.utc - start) > ready_timeout || has_ip?(vm_ip, vm) do
|
334
|
+
action_handler.report_progress(
|
335
|
+
"IP addresses found: #{all_ips_for(vm)}")
|
336
|
+
vm_ip ||= ip_to_bootstrap(bootstrap_options, vm)
|
337
|
+
sleep 5
|
275
338
|
end
|
339
|
+
end
|
276
340
|
|
277
|
-
|
341
|
+
def all_ips_for(vm)
|
342
|
+
vm.guest.net.map { |net| net.ipAddress}.flatten
|
343
|
+
end
|
344
|
+
|
345
|
+
def has_ip?(ip, vm)
|
346
|
+
all_ips_for(vm).include?(ip)
|
278
347
|
end
|
279
348
|
|
280
349
|
# Connect to machine without acquiring it
|
@@ -313,8 +382,7 @@ module ChefProvisioningVsphere
|
|
313
382
|
vm = vm_for(machine_spec)
|
314
383
|
if vm
|
315
384
|
action_handler.perform_action "Power on VM [#{vm.parent.name}/#{vm.name}]" do
|
316
|
-
|
317
|
-
start_vm(vm, bootstrap_options[:ssh][:port])
|
385
|
+
start_vm(vm, machine_options[:bootstrap_options][:ssh][:port])
|
318
386
|
end
|
319
387
|
end
|
320
388
|
end
|
@@ -330,27 +398,27 @@ module ChefProvisioningVsphere
|
|
330
398
|
protected
|
331
399
|
|
332
400
|
def setup_ubuntu_dns(machine, bootstrap_options, machine_spec)
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
end
|
401
|
+
host_lookup = machine.execute_always('host google.com')
|
402
|
+
if host_lookup.exitstatus != 0
|
403
|
+
if host_lookup.stdout.include?("setlocale: LC_ALL")
|
404
|
+
machine.execute_always('locale-gen en_US && update-locale LANG=en_US')
|
405
|
+
end
|
406
|
+
distro = machine.execute_always("lsb_release -i | sed -e 's/Distributor ID://g'").stdout.strip
|
407
|
+
Chef::Log.info "Found distro:#{distro}"
|
408
|
+
if distro == 'Ubuntu'
|
409
|
+
distro_version = (machine.execute_always("lsb_release -r | sed -e s/[^0-9.]//g")).stdout.strip.to_f
|
410
|
+
Chef::Log.info "Found distro version:#{distro_version}"
|
411
|
+
if distro_version>= 12.04
|
412
|
+
Chef::Log.info "Ubuntu version 12.04 or greater. Need to patch DNS."
|
413
|
+
interfaces_file = "/etc/network/interfaces"
|
414
|
+
nameservers = bootstrap_options[:customization_spec][:ipsettings][:dnsServerList].join(' ')
|
415
|
+
machine.execute_always("if ! cat #{interfaces_file} | grep -q dns-search ; then echo 'dns-search #{bootstrap_options[:customization_spec][:domain]}' >> #{interfaces_file} ; fi")
|
416
|
+
machine.execute_always("if ! cat #{interfaces_file} | grep -q dns-nameservers ; then echo 'dns-nameservers #{nameservers}' >> #{interfaces_file} ; fi")
|
417
|
+
machine.execute_always('/etc/init.d/networking restart')
|
418
|
+
machine.execute_always('apt-get -qq update')
|
352
419
|
end
|
353
420
|
end
|
421
|
+
end
|
354
422
|
end
|
355
423
|
|
356
424
|
def has_static_ip(bootstrap_options)
|
@@ -368,18 +436,20 @@ module ChefProvisioningVsphere
|
|
368
436
|
|
369
437
|
def remaining_wait_time(machine_spec, machine_options)
|
370
438
|
if machine_spec.location['started_at']
|
371
|
-
machine_options[:start_timeout]
|
439
|
+
(machine_options[:start_timeout] || 600) -
|
440
|
+
(Time.now.utc - Time.parse(machine_spec.location['started_at']))
|
372
441
|
else
|
373
|
-
machine_options[:create_timeout]
|
442
|
+
(machine_options[:create_timeout] || 600) -
|
443
|
+
(Time.now.utc - Time.parse(machine_spec.location['allocated_at']))
|
374
444
|
end
|
375
445
|
end
|
376
446
|
|
377
447
|
def wait_until_ready(action_handler, machine_spec, machine_options, vm)
|
378
448
|
if vm.guest.toolsRunningStatus != "guestToolsRunning"
|
379
|
-
perform_action = true
|
380
449
|
if action_handler.should_perform_actions
|
381
450
|
action_handler.report_progress "waiting for #{machine_spec.name} (#{vm.config.instanceUuid} on #{driver_url}) to be ready ..."
|
382
|
-
until remaining_wait_time(machine_spec, machine_options) < 0 ||
|
451
|
+
until remaining_wait_time(machine_spec, machine_options) < 0 ||
|
452
|
+
(vm.guest.toolsRunningStatus == "guestToolsRunning" && !vm.guest.ipAddress.nil? && vm.guest.ipAddress.length > 0) do
|
383
453
|
print "."
|
384
454
|
sleep 5
|
385
455
|
end
|
@@ -396,32 +466,21 @@ module ChefProvisioningVsphere
|
|
396
466
|
end
|
397
467
|
end
|
398
468
|
|
399
|
-
def
|
400
|
-
|
401
|
-
bootstrap_options = bootstrap_options.to_hash
|
402
|
-
tags = {
|
403
|
-
'Name' => machine_spec.name,
|
404
|
-
'BootstrapId' => machine_spec.id,
|
405
|
-
'BootstrapHost' => Socket.gethostname,
|
406
|
-
'BootstrapUser' => Etc.getlogin
|
407
|
-
}
|
408
|
-
# User-defined tags override the ones we set
|
409
|
-
tags.merge!(bootstrap_options[:tags]) if bootstrap_options[:tags]
|
410
|
-
bootstrap_options.merge!({ :tags => tags })
|
411
|
-
bootstrap_options[:name] ||= machine_spec.name
|
412
|
-
bootstrap_options
|
413
|
-
end
|
414
|
-
|
415
|
-
def clone_vm(action_handler, bootstrap_options)
|
416
|
-
vm_name = bootstrap_options[:name]
|
417
|
-
datacenter = bootstrap_options[:datacenter]
|
469
|
+
def clone_vm(action_handler, bootstrap_options, machine_name)
|
470
|
+
datacenter = bootstrap_options[:datacenter]
|
418
471
|
|
419
|
-
vm = find_vm(datacenter, bootstrap_options[:vm_folder],
|
472
|
+
vm = find_vm(datacenter, bootstrap_options[:vm_folder], machine_name)
|
420
473
|
return vm if vm
|
421
474
|
|
422
475
|
vm_template = vm_template_for(bootstrap_options)
|
423
476
|
|
424
|
-
do_vm_clone(
|
477
|
+
do_vm_clone(
|
478
|
+
action_handler,
|
479
|
+
datacenter,
|
480
|
+
vm_template,
|
481
|
+
machine_name,
|
482
|
+
bootstrap_options
|
483
|
+
)
|
425
484
|
end
|
426
485
|
|
427
486
|
def vm_template_for(bootstrap_options)
|
@@ -431,16 +490,23 @@ module ChefProvisioningVsphere
|
|
431
490
|
find_vm(datacenter, template_folder, template_name) or raise("vSphere VM Template not found [#{template_folder}/#{template_name}]")
|
432
491
|
end
|
433
492
|
|
434
|
-
def machine_for(machine_spec, machine_options
|
435
|
-
|
436
|
-
if !vm
|
493
|
+
def machine_for(machine_spec, machine_options)
|
494
|
+
if machine_spec.location.nil?
|
437
495
|
raise "Server for node #{machine_spec.name} has not been created!"
|
438
496
|
end
|
439
497
|
|
498
|
+
transport = transport_for(
|
499
|
+
machine_spec,
|
500
|
+
machine_options[:bootstrap_options][:ssh]
|
501
|
+
)
|
502
|
+
strategy = convergence_strategy_for(machine_spec, machine_options)
|
503
|
+
|
440
504
|
if machine_spec.location['is_windows']
|
441
|
-
Chef::Provisioning::Machine::WindowsMachine.new(
|
505
|
+
Chef::Provisioning::Machine::WindowsMachine.new(
|
506
|
+
machine_spec, transport, strategy)
|
442
507
|
else
|
443
|
-
Chef::Provisioning::Machine::UnixMachine.new(
|
508
|
+
Chef::Provisioning::Machine::UnixMachine.new(
|
509
|
+
machine_spec, transport, strategy)
|
444
510
|
end
|
445
511
|
end
|
446
512
|
|
@@ -466,7 +532,10 @@ module ChefProvisioningVsphere
|
|
466
532
|
end
|
467
533
|
|
468
534
|
def wait_for_transport(action_handler, machine_spec, machine_options, vm)
|
469
|
-
transport = transport_for(
|
535
|
+
transport = transport_for(
|
536
|
+
machine_spec,
|
537
|
+
machine_options[:bootstrap_options][:ssh]
|
538
|
+
)
|
470
539
|
if !transport.available?
|
471
540
|
if action_handler.should_perform_actions
|
472
541
|
action_handler.report_progress "waiting for #{machine_spec.name} (#{vm.config.instanceUuid} on #{driver_url}) to be connectable (transport up and running) ..."
|
@@ -481,41 +550,48 @@ module ChefProvisioningVsphere
|
|
481
550
|
end
|
482
551
|
end
|
483
552
|
|
484
|
-
def transport_for(
|
485
|
-
|
486
|
-
|
553
|
+
def transport_for(
|
554
|
+
machine_spec,
|
555
|
+
remoting_options,
|
556
|
+
ip = machine_spec.location['ipaddress']
|
557
|
+
)
|
558
|
+
if machine_spec.location['is_windows']
|
559
|
+
create_winrm_transport(ip, remoting_options)
|
487
560
|
else
|
488
|
-
create_ssh_transport(
|
561
|
+
create_ssh_transport(ip, remoting_options)
|
489
562
|
end
|
490
563
|
end
|
491
564
|
|
492
|
-
def create_winrm_transport(
|
565
|
+
def create_winrm_transport(host, options)
|
493
566
|
require 'chef/provisioning/transport/winrm'
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
winrm_options[:disable_sspi] = true
|
501
|
-
else
|
502
|
-
winrm_options[:basic_auth_only] = true
|
503
|
-
end
|
567
|
+
opt = options[:user].include?("\\") ? :disable_sspi : :basic_auth_only
|
568
|
+
winrm_options = {
|
569
|
+
user: "#{options[:user]}",
|
570
|
+
pass: options[:password],
|
571
|
+
opt => true
|
572
|
+
}
|
504
573
|
|
505
|
-
Chef::Provisioning::Transport::WinRM.new(
|
574
|
+
Chef::Provisioning::Transport::WinRM.new(
|
575
|
+
"http://#{host}:5985/wsman",
|
576
|
+
:plaintext,
|
577
|
+
winrm_options,
|
578
|
+
config
|
579
|
+
)
|
506
580
|
end
|
507
581
|
|
508
|
-
def create_ssh_transport(
|
582
|
+
def create_ssh_transport(host, options)
|
509
583
|
require 'chef/provisioning/transport/ssh'
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
584
|
+
ssh_user = options[:user]
|
585
|
+
Chef::Provisioning::Transport::SSH.new(
|
586
|
+
host,
|
587
|
+
ssh_user,
|
588
|
+
options,
|
589
|
+
{},
|
590
|
+
config
|
591
|
+
)
|
516
592
|
end
|
517
593
|
|
518
|
-
def
|
594
|
+
def ip_to_bootstrap(bootstrap_options, vm)
|
519
595
|
if has_static_ip(bootstrap_options)
|
520
596
|
bootstrap_options[:customization_spec][:ipsettings][:ip]
|
521
597
|
else
|