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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0d79d0a2cda2ae2c35a26785805165a0449db2ab
4
- data.tar.gz: f70880364d9a538115a8b7eeae608971ea9e4246
3
+ metadata.gz: 990036a8b6dcc42e111ed4acb92aa90c5fe59f1d
4
+ data.tar.gz: 2767a8e7fd769b90954e57b06eecccfa0fd29736
5
5
  SHA512:
6
- metadata.gz: 573d1b2bd5a273e6edd62728e1dd7054f6859d7663f6533b0ad69e89b3af02f45fecd6515066751d3b5ac9afa71041bf9941c5c71aedecca1551974c97d4ccf8
7
- data.tar.gz: 2ba913e525d49af3799a44aebca5131ebb4eac8f369158f19c8a299d1045017a9697f5c8e1f38b69f28cb683bc9c467ea911836829b1c34a703a5d9282856b75
6
+ metadata.gz: 0784aeb6843b433d16f5aa93aee499e55ed0aad8b2dd6b8c6378258d9c504ac78fcac3d6cf7e4abdda19e580b6c58ce8a58853db7d2342ab38a943f51e91329c
7
+ data.tar.gz: e68182faff627baf71b3b0074cc14fac995908123f0bcdef2e263b70cd147496a40fb299b7d9797fd31da826f37176bc7ab9781bd6fb8a2b045a913b6742f0b2
data/Gemfile CHANGED
@@ -2,4 +2,4 @@
2
2
  source "https://rubygems.org"
3
3
  gemspec
4
4
 
5
- gem "chef", "~> 12.1"
5
+ gem "chef", "~> 12.3"
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 = 'Apache 2.0'
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
- url, config = ChefProvisioningVsphere::VsphereDriver.canonicalize_url(nil, {:driver_options => driver_options})
9
- with_driver url, driver_options, &block
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
- new_defaults = {
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
- @connect_options = config[:driver_options][:connect_options].to_hash
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 "Checking to see if #{machine_spec.location} has been created..."
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 "returning existing machine"
118
+ Chef::Log.warn 'returning existing machine'
148
119
  return vm
149
120
  else
150
- Chef::Log.warn "Machine #{machine_spec.name} (#{machine_spec.location['server_id']} on #{driver_url}) no longer exists. Recreating ..."
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 = bootstrap_options_for(machine_spec, machine_options)
154
- vm = nil
128
+ bootstrap_options = machine_options[:bootstrap_options]
155
129
 
156
- if bootstrap_options[:ssh]
157
- wait_on_port = bootstrap_options[:ssh][:port]
158
- raise "Must specify bootstrap_options[:ssh][:port]" if wait_on_port.nil?
159
- else
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
- description = [ "creating machine #{machine_spec.name} on #{driver_url}" ]
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
- vm = find_vm(bootstrap_options[:datacenter], bootstrap_options[:vm_folder], machine_spec.name)
169
- server_id = nil
170
- if vm
171
- Chef::Log.info "machine already created: #{bootstrap_options[:vm_folder]}/#{machine_spec.name}"
172
- else
173
- vm = clone_vm(action_handler, bootstrap_options)
174
- end
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
- machine_spec.location['key_name'] = bootstrap_options[:key_name] if bootstrap_options[:key_name]
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
- action_handler.performed_action "machine #{machine_spec.name} created as #{machine_spec.location['server_id']} on #{driver_url}"
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 associated with it, or server does not exist."
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
- wait_until_ready(action_handler, machine_spec, machine_options, vm)
195
+ bootstrap_options = machine_options[:bootstrap_options]
201
196
 
202
- bootstrap_options = bootstrap_options_for(machine_spec, machine_options)
197
+ transport_respond?(
198
+ machine_options,
199
+ vm,
200
+ action_handler,
201
+ machine_spec
202
+ )
203
203
 
204
- transport = nil
205
- vm_ip = ip_for(bootstrap_options, vm)
206
- if !vm_ip.nil?
207
- transport = transport_for(machine_spec, machine_options, vm)
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
- if transport.nil? || !transport.available? || !(vm.guest.net.map { |net| net.ipAddress}.flatten).include?(vm_ip)
211
- action_handler.report_progress "waiting up to #{machine_options[:ready_timeout]} seconds for customizations to complete and find #{vm_ip}"
212
- now = Time.now.utc
211
+ machine
212
+ end
213
213
 
214
- until (Time.now.utc - now) > machine_options[:ready_timeout] || (vm.guest.net.map { |net| net.ipAddress}.flatten).include?(vm_ip) do
215
- action_handler.report_progress "IP addresses on #{machine_spec.name} are #{vm.guest.net.map { |net| net.ipAddress}.flatten}"
216
- vm_ip = ip_for(bootstrap_options, vm) if vm_ip.nil?
217
- sleep 5
218
- end
219
- if !(vm.guest.net.map { |net| net.ipAddress}.flatten).include?(vm_ip)
220
- action_handler.report_progress "rebooting..."
221
- if vm.guest.toolsRunningStatus != "guestToolsRunning"
222
- action_handler.report_progress "tools have stopped. current power state is #{vm.runtime.powerState} and tools state is #{vm.guest.toolsRunningStatus}. powering up server..."
223
- start_vm(vm)
224
- else
225
- restart_server(action_handler, machine_spec, vm)
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
- domain = bootstrap_options[:customization_spec][:domain]
239
- if vm.config.guestId.start_with?('win') && domain != 'local'
240
- now = Time.now.utc
241
- trimmed_name = machine_spec.name.byteslice(0,15)
242
- expected_name="#{trimmed_name}.#{domain}"
243
- action_handler.report_progress "waiting to domain join and be named #{expected_name}"
244
- until (Time.now.utc - now) > 30 || (vm.guest.hostName == expected_name) do
245
- print "."
246
- sleep 5
247
- end
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 since we stopped waiting
254
- if machine_spec.location['started_at'] || remaining_wait_time(machine_spec, machine_options) < -(10*60)
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 "Machine #{machine_spec.name} (#{server.config.instanceUuid} on #{driver_url}) was started but SSH did not come up. Rebooting machine in an attempt to unstick it ..."
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
- machine = machine_for(machine_spec, machine_options, vm)
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
- new_nics = add_extra_nic(action_handler, vm_template_for(bootstrap_options), bootstrap_options, vm)
267
- if is_windows?(vm) && !new_nics.nil?
268
- new_nics.each do |nic|
269
- machine.execute_always("Disable-Netadapter -Name '#{nic.device.deviceInfo.label}' -Confirm:$false")
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
- if has_static_ip(bootstrap_options) && !is_windows?(vm)
274
- setup_ubuntu_dns(machine, bootstrap_options, machine_spec)
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
- machine
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
- bootstrap_options = bootstrap_options_for(machine_spec, machine_options)
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
- host_lookup = machine.execute_always('host google.com')
334
- if host_lookup.exitstatus != 0
335
- if host_lookup.stdout.include?("setlocale: LC_ALL")
336
- machine.execute_always('locale-gen en_US && update-locale LANG=en_US')
337
- end
338
- distro = machine.execute_always("lsb_release -i | sed -e 's/Distributor ID://g'").stdout.strip
339
- Chef::Log.info "Found distro:#{distro}"
340
- if distro == 'Ubuntu'
341
- distro_version = (machine.execute_always("lsb_release -r | sed -e s/[^0-9.]//g")).stdout.strip.to_f
342
- Chef::Log.info "Found distro version:#{distro_version}"
343
- if distro_version>= 12.04
344
- Chef::Log.info "Ubuntu version 12.04 or greater. Need to patch DNS."
345
- interfaces_file = "/etc/network/interfaces"
346
- nameservers = bootstrap_options[:customization_spec][:ipsettings][:dnsServerList].join(' ')
347
- machine.execute_always("if ! cat #{interfaces_file} | grep -q dns-search ; then echo 'dns-search #{bootstrap_options[:customization_spec][:domain]}' >> #{interfaces_file} ; fi")
348
- machine.execute_always("if ! cat #{interfaces_file} | grep -q dns-nameservers ; then echo 'dns-nameservers #{nameservers}' >> #{interfaces_file} ; fi")
349
- machine.execute_always('/etc/init.d/networking restart')
350
- machine.execute_always('apt-get -qq update')
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] - (Time.now.utc - Time.parse(machine_spec.location['started_at']))
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] - (Time.now.utc - Time.parse(machine_spec.location['allocated_at']))
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 || (vm.guest.toolsRunningStatus == "guestToolsRunning" && (vm.guest.ipAddress.nil? || vm.guest.ipAddress.length > 0)) do
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 bootstrap_options_for(machine_spec, machine_options)
400
- bootstrap_options = machine_options[:bootstrap_options] || {}
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], vm_name)
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(action_handler, datacenter, vm_template, vm_name, bootstrap_options)
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, vm = nil)
435
- vm ||= vm_for(machine_spec)
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(machine_spec, transport_for(machine_spec, machine_options, vm), convergence_strategy_for(machine_spec, machine_options))
505
+ Chef::Provisioning::Machine::WindowsMachine.new(
506
+ machine_spec, transport, strategy)
442
507
  else
443
- Chef::Provisioning::Machine::UnixMachine.new(machine_spec, transport_for(machine_spec, machine_options, vm), convergence_strategy_for(machine_spec, machine_options))
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(machine_spec, machine_options, vm)
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(machine_spec, machine_options, vm)
485
- if is_windows?(vm)
486
- create_winrm_transport(machine_spec, machine_options, vm)
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(machine_spec, machine_options, vm)
561
+ create_ssh_transport(ip, remoting_options)
489
562
  end
490
563
  end
491
564
 
492
- def create_winrm_transport(machine_spec, machine_options, vm)
565
+ def create_winrm_transport(host, options)
493
566
  require 'chef/provisioning/transport/winrm'
494
- bootstrap_options = bootstrap_options_for(machine_spec, machine_options)
495
- ssh_options = bootstrap_options[:ssh]
496
- remote_host = machine_spec.location['ipaddress'] || ip_for(bootstrap_options, vm)
497
-
498
- winrm_options = {:user => "#{ssh_options[:user]}", :pass => ssh_options[:password]}
499
- if ssh_options[:user].include?("\\")
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("http://#{remote_host}:5985/wsman", :plaintext, winrm_options, config)
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(machine_spec, machine_options, vm)
582
+ def create_ssh_transport(host, options)
509
583
  require 'chef/provisioning/transport/ssh'
510
- bootstrap_options = bootstrap_options_for(machine_spec, machine_options)
511
- ssh_options = bootstrap_options[:ssh]
512
- ssh_user = ssh_options[:user]
513
- remote_host = machine_spec.location['ipaddress'] || ip_for(bootstrap_options, vm)
514
-
515
- Chef::Provisioning::Transport::SSH.new(remote_host, ssh_user, ssh_options, {}, config)
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 ip_for(bootstrap_options, vm)
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