chef-provisioning-vsphere 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|