chef-provisioning-vsphere 2.0.2 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +22 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- data/.gitignore +3 -1
- data/.travis.yml +7 -0
- data/CHANGELOG.md +17 -2
- data/Gemfile +1 -1
- data/README.md +5 -1
- data/Rakefile +20 -13
- data/chef-provisioning-vsphere.gemspec +26 -26
- data/lib/chef/provisioning/driver_init/vsphere.rb +2 -2
- data/lib/chef/provisioning/vsphere_driver.rb +9 -2
- data/lib/chef/provisioning/vsphere_driver/clone_spec_builder.rb +37 -13
- data/lib/chef/provisioning/vsphere_driver/driver.rb +233 -86
- data/lib/chef/provisioning/vsphere_driver/version.rb +3 -1
- data/lib/chef/provisioning/vsphere_driver/vm_helper.rb +22 -5
- data/lib/chef/provisioning/vsphere_driver/vsphere_helpers.rb +118 -26
- data/lib/chef/provisioning/vsphere_driver/vsphere_url.rb +23 -13
- data/lib/kitchen/driver/vsphere.rb +29 -13
- data/spec/spec_helper.rb +19 -0
- metadata +34 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e921ec7be5d161723bdd1e333b4d1a93ec4a9e09
|
4
|
+
data.tar.gz: 2f3c474699229fdfa75df67513b7570e1ce86c15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2e773ae65c3cefceb7f46a0d3c2dbc1a7242d80c3b1c998b35485027fb1dac2a15d97bae89d57b1194a7a3d87c6ac327229370ed18514b8fb2bd7cea3ce727c7
|
7
|
+
data.tar.gz: c3dccf9cb837eb675865706276cb5a0d1239488dbd4c23e21d8b57fb4cd3b26a92a641c844eb82a885b535417d5791e89b11bbb5b91de65d231a30346a1caba8
|
@@ -0,0 +1,22 @@
|
|
1
|
+
### Versions:
|
2
|
+
<!--- Version of the software where you are encountering the issue --->
|
3
|
+
<!-- You should probably update in this is not newest release.--->
|
4
|
+
* Version of Chef-Provisioning:
|
5
|
+
* Version of Chef-Provisioning-vSphere:
|
6
|
+
|
7
|
+
### Platform Details
|
8
|
+
<!--- What version of vSphere/vCenter are you running? What version of ESXi are you using too?--->
|
9
|
+
* Version of vSphere/vCenter:
|
10
|
+
* Version of ESXi:
|
11
|
+
|
12
|
+
### Scenario:
|
13
|
+
<!--- What you are trying to achieve and you can't?--->
|
14
|
+
|
15
|
+
### Steps to Reproduce:
|
16
|
+
<!--- If you are filing an issue what are the things we need to do in order to repro your problem? How are you using this cookbook or any resources it includes?--->
|
17
|
+
|
18
|
+
### Expected Result:
|
19
|
+
<!--- What are you expecting to happen as the consequence of above reproduction steps?--->
|
20
|
+
|
21
|
+
### Actual Result:
|
22
|
+
<!--- What actually happens after the reproduction steps? Include the error output or a link to a gist if possible.--->
|
@@ -0,0 +1,14 @@
|
|
1
|
+
### Description
|
2
|
+
|
3
|
+
<!--- Describe what this change achieves--->
|
4
|
+
|
5
|
+
### Issues Resolved
|
6
|
+
|
7
|
+
<!--- List any existing issues this PR resolves--->
|
8
|
+
|
9
|
+
### Check List
|
10
|
+
|
11
|
+
- [ ] All tests pass.
|
12
|
+
- [ ] All style checks pass.
|
13
|
+
- [ ] Functionality includes testing.
|
14
|
+
- [ ] Functionality has been documented in the README if applicable
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,22 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [2.0.
|
4
|
-
[Full Changelog](https://github.com/chef-partners/chef-provisioning-vsphere/compare/v2.0.
|
3
|
+
## [2.0.3](https://github.com/chef-partners/chef-provisioning-vsphere/tree/2.0.3) (2017-05-22)
|
4
|
+
[Full Changelog](https://github.com/chef-partners/chef-provisioning-vsphere/compare/v2.0.2...2.0.3)
|
5
|
+
|
6
|
+
**Closed issues:**
|
7
|
+
|
8
|
+
- Patch on transport\_respond? [\#31](https://github.com/chef-partners/chef-provisioning-vsphere/issues/31)
|
9
|
+
- Github Templates [\#28](https://github.com/chef-partners/chef-provisioning-vsphere/issues/28)
|
10
|
+
|
11
|
+
**Merged pull requests:**
|
12
|
+
|
13
|
+
- Patch on transport\_respond? [\#32](https://github.com/chef-partners/chef-provisioning-vsphere/pull/32) ([jcalonsoh](https://github.com/jcalonsoh))
|
14
|
+
- Added github templates [\#30](https://github.com/chef-partners/chef-provisioning-vsphere/pull/30) ([jjasghar](https://github.com/jjasghar))
|
15
|
+
- waffle.io Badge [\#29](https://github.com/chef-partners/chef-provisioning-vsphere/pull/29) ([waffle-iron](https://github.com/waffle-iron))
|
16
|
+
- Time to do doc all the things! [\#27](https://github.com/chef-partners/chef-provisioning-vsphere/pull/27) ([jjasghar](https://github.com/jjasghar))
|
17
|
+
|
18
|
+
## [v2.0.2](https://github.com/chef-partners/chef-provisioning-vsphere/tree/v2.0.2) (2017-05-13)
|
19
|
+
[Full Changelog](https://github.com/chef-partners/chef-provisioning-vsphere/compare/v2.0.0...v2.0.2)
|
5
20
|
|
6
21
|
**Closed issues:**
|
7
22
|
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://img.shields.io/gem/v/chef-provisioning-vsphere.svg)][gem]
|
4
4
|
[![Build Status](https://travis-ci.org/chef-partners/chef-provisioning-vsphere.svg?branch=master)][travis]
|
5
|
+
[![Inline docs](http://inch-ci.org/github/chef-partners/chef-provisioning-vsphere.svg?branch=master)](http://inch-ci.org/github/chef-partners/chef-provisioning-vsphere)
|
6
|
+
[![Stories in Ready](https://badge.waffle.io/chef-partners/chef-provisioning-vsphere.png?label=ready&title=Ready)](https://waffle.io/chef-partners/chef-provisioning-vsphere?utm_source=badge)
|
5
7
|
|
6
8
|
This is a [chef-provisioning](https://github.com/chef/chef-provisioning) provisioner for [VMware vSphere](http://www.vmware.com/products/vsphere).
|
7
9
|
|
@@ -321,7 +323,7 @@ platforms:
|
|
321
323
|
- 10
|
322
324
|
- 10
|
323
325
|
- 10
|
324
|
-
|
326
|
+
|
325
327
|
suites:
|
326
328
|
- name: default
|
327
329
|
runlist:
|
@@ -346,5 +348,7 @@ You can run then `kitchen diagnose` to verify the nodes and settings that will b
|
|
346
348
|
4. Push to the branch (`git push origin my-new-feature`)
|
347
349
|
5. Create a new Pull Request
|
348
350
|
|
351
|
+
We have attempted to `TODO` markings. If you find one, whether it's documentation or a feature, it's a great place to start helping out. `$ grep -r "TODO" lib/`
|
352
|
+
|
349
353
|
[gem]: https://rubygems.org/gems/chef-provisioning-vsphere
|
350
354
|
[travis]: https://travis-ci.org/chef-partners/chef-provisioning-vsphere
|
data/Rakefile
CHANGED
@@ -1,34 +1,41 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
require "chef/provisioning/vsphere_driver/version"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
require "chefstyle"
|
6
|
+
require "rubocop/rake_task"
|
7
|
+
require "yard"
|
6
8
|
|
7
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) +
|
9
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + "/lib")
|
8
10
|
|
9
11
|
RuboCop::RakeTask.new(:style) do |task|
|
10
|
-
task.options <<
|
12
|
+
task.options << "--display-cop-names"
|
11
13
|
end
|
12
14
|
|
13
15
|
RSpec::Core::RakeTask.new(:unit) do |task|
|
14
|
-
task.pattern =
|
15
|
-
task.rspec_opts = [
|
16
|
+
task.pattern = "spec/unit_tests/*_spec.rb"
|
17
|
+
task.rspec_opts = ["--color", "-f documentation"]
|
16
18
|
end
|
17
19
|
|
18
20
|
RSpec::Core::RakeTask.new(:integration) do |task|
|
19
|
-
task.pattern =
|
20
|
-
task.rspec_opts = [
|
21
|
+
task.pattern = "spec/integration_tests/*_spec.rb"
|
22
|
+
task.rspec_opts = ["--color", "-f documentation", "--out rspec.txt"]
|
21
23
|
end
|
22
24
|
|
23
25
|
begin
|
24
|
-
require
|
26
|
+
require "github_changelog_generator/task"
|
25
27
|
|
26
28
|
GitHubChangelogGenerator::RakeTask.new :changelog do |config|
|
27
29
|
config.future_release = ChefProvisioningVsphere::VERSION
|
28
30
|
config.issues = true
|
29
31
|
end
|
30
32
|
rescue LoadError
|
31
|
-
puts
|
33
|
+
puts "github_changelog_generator is not available. gem install github_changelog_generator to generate changelogs"
|
32
34
|
end
|
33
35
|
|
34
|
-
|
36
|
+
YARD::Rake::YardocTask.new do |t|
|
37
|
+
t.files = ["lib/**/*.rb"] # optional
|
38
|
+
t.stats_options = ["--list-undoc"] # optional
|
39
|
+
end
|
40
|
+
|
41
|
+
task default: [:style, :unit]
|
@@ -1,37 +1,37 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__) +
|
3
|
-
require
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + "/lib")
|
3
|
+
require "chef/provisioning/vsphere_driver/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name =
|
6
|
+
s.name = "chef-provisioning-vsphere"
|
7
7
|
s.version = ChefProvisioningVsphere::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.extra_rdoc_files = [
|
10
|
-
s.summary =
|
9
|
+
s.extra_rdoc_files = ["README.md"]
|
10
|
+
s.summary = "Provisioner for creating vSphere VM instances in Chef Provisioning."
|
11
11
|
s.description = s.summary
|
12
|
-
s.authors = [
|
13
|
-
s.email =
|
14
|
-
s.homepage =
|
15
|
-
s.license =
|
16
|
-
|
17
|
-
s.
|
18
|
-
s.
|
19
|
-
|
20
|
-
s.require_path = 'lib'
|
12
|
+
s.authors = ["CenturyLink Cloud", "JJ Asghar"]
|
13
|
+
s.email = "jj@chef.io"
|
14
|
+
s.homepage = "https://github.com/chef-partners/chef-provisioning-vsphere"
|
15
|
+
s.license = "MIT"
|
16
|
+
s.bindir = "bin"
|
17
|
+
s.executables = %w{}
|
18
|
+
s.require_path = "lib"
|
21
19
|
s.files = `git ls-files -z`.split("\x0")
|
22
20
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
23
21
|
|
24
|
-
s.add_dependency
|
25
|
-
s.add_dependency
|
26
|
-
s.add_dependency
|
27
|
-
s.add_dependency
|
28
|
-
s.add_dependency
|
22
|
+
s.add_dependency "rbvmomi", "~> 1.10"
|
23
|
+
s.add_dependency "chef-provisioning", "~> 2.0"
|
24
|
+
s.add_dependency "github_changelog_generator"
|
25
|
+
s.add_dependency "cheffish", ">= 4.0", "< 14.0"
|
26
|
+
s.add_dependency "chef", ">= 12.0", "< 14.0"
|
29
27
|
|
30
|
-
s.add_development_dependency
|
31
|
-
s.add_development_dependency
|
32
|
-
s.add_development_dependency
|
33
|
-
s.add_development_dependency
|
34
|
-
s.add_development_dependency
|
35
|
-
s.add_development_dependency
|
36
|
-
s.add_development_dependency
|
28
|
+
s.add_development_dependency "rspec"
|
29
|
+
s.add_development_dependency "rake"
|
30
|
+
s.add_development_dependency "chefstyle"
|
31
|
+
s.add_development_dependency "pry"
|
32
|
+
s.add_development_dependency "pry-byebug"
|
33
|
+
s.add_development_dependency "pry-stack_explorer"
|
34
|
+
s.add_development_dependency "rb-readline"
|
35
|
+
s.add_development_dependency "simplecov"
|
36
|
+
s.add_development_dependency "yard"
|
37
37
|
end
|
@@ -1,4 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
2
|
+
require "chef/provisioning/vsphere_driver"
|
3
3
|
|
4
|
-
Chef::Provisioning.register_driver_class(
|
4
|
+
Chef::Provisioning.register_driver_class("vsphere", ChefProvisioningVsphere::VsphereDriver)
|
@@ -1,10 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
3
|
-
require
|
2
|
+
require "chef/provisioning"
|
3
|
+
require "chef/provisioning/vsphere_driver/driver"
|
4
4
|
|
5
|
+
# The main Chef class for all the Chef code!
|
5
6
|
class Chef
|
7
|
+
# The main Chef module for the Domain Specialized Language
|
6
8
|
module DSL
|
9
|
+
# The main Chef module for the the Recipe in side of Chef's DSL
|
7
10
|
module Recipe
|
11
|
+
# Creates the url object for Chef-Provisioning to leverage.
|
12
|
+
#
|
13
|
+
# @param [Object] driver_options Used from the Chef Provisioning to connect
|
14
|
+
# @param [Object] block TODO
|
8
15
|
def with_vsphere_driver(driver_options, &block)
|
9
16
|
url = ChefProvisioningVsphere::VsphereDriver.canonicalize_url(
|
10
17
|
nil, driver_options
|
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Provisions machines in vSphere.
|
2
4
|
module ChefProvisioningVsphere
|
5
|
+
# Creates a cspec for VMware
|
3
6
|
class CloneSpecBuilder
|
4
7
|
def initialize(vsphere_helper, action_handler)
|
5
8
|
@vsphere_helper = vsphere_helper
|
@@ -9,6 +12,11 @@ module ChefProvisioningVsphere
|
|
9
12
|
attr_reader :vsphere_helper
|
10
13
|
attr_reader :action_handler
|
11
14
|
|
15
|
+
# The main build method.
|
16
|
+
#
|
17
|
+
# @param [String] options Options set from Chef-Provisioning.
|
18
|
+
# @param [String] vm_template The VM template to clone from.
|
19
|
+
# @param [String] vm_name The VM name to create.
|
12
20
|
def build(vm_template, vm_name, options)
|
13
21
|
clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(
|
14
22
|
location: relocate_spec_for(vm_template, options),
|
@@ -52,6 +60,10 @@ module ChefProvisioningVsphere
|
|
52
60
|
clone_spec
|
53
61
|
end
|
54
62
|
|
63
|
+
# Figure out or declare where you need to bootstrap the vm
|
64
|
+
#
|
65
|
+
# @param [String] options Options set from Chef-Provisioning.
|
66
|
+
# @param [String] vm_template The VM template to clone from.
|
55
67
|
def relocate_spec_for(vm_template, options)
|
56
68
|
rspec = RbVmomi::VIM.VirtualMachineRelocateSpec
|
57
69
|
host = nil
|
@@ -66,12 +78,12 @@ module ChefProvisioningVsphere
|
|
66
78
|
elsif vm_template.config.template && !host.nil?
|
67
79
|
rspec.pool = host.parent.resourcePool # assign to the "invisible" pool root
|
68
80
|
elsif vm_template.config.template
|
69
|
-
raise
|
81
|
+
raise "either :host or :resource_pool must be specified when cloning from a VM Template"
|
70
82
|
end
|
71
83
|
|
72
84
|
if options[:use_linked_clone]
|
73
85
|
if vm_template.config.template
|
74
|
-
Chef::Log.warn(
|
86
|
+
Chef::Log.warn("Using a VM Template, ignoring use_linked_clone.")
|
75
87
|
else
|
76
88
|
vsphere_helper.create_delta_disk(vm_template)
|
77
89
|
rspec.diskMoveType = :moveChildMostDiskBacking
|
@@ -85,19 +97,24 @@ module ChefProvisioningVsphere
|
|
85
97
|
rspec
|
86
98
|
end
|
87
99
|
|
100
|
+
# Verify and create all the options needed for Customization Specs
|
101
|
+
#
|
102
|
+
# @param [String] options Options set from Chef-Provisioning.
|
103
|
+
# @param [String] vm_name The VM name that is set.
|
104
|
+
# @param [String] vm_template The VM template to clone from.
|
88
105
|
def customization_options_from(vm_template, vm_name, options)
|
89
106
|
if options.key?(:customization_spec)
|
90
107
|
if options[:customization_spec].is_a?(Hash) ||
|
91
|
-
|
108
|
+
options[:customization_spec].is_a?(Cheffish::MergedConfig)
|
92
109
|
cust_options = options[:customization_spec]
|
93
110
|
ip_settings = cust_options[:ipsettings]
|
94
111
|
cust_domain = cust_options[:domain]
|
95
112
|
|
96
|
-
raise ArgumentError,
|
113
|
+
raise ArgumentError, "domain is required" unless cust_domain
|
97
114
|
cust_ip_settings = nil
|
98
115
|
if ip_settings && ip_settings.key?(:ip)
|
99
116
|
unless cust_options[:ipsettings].key?(:subnetMask)
|
100
|
-
raise ArgumentError,
|
117
|
+
raise ArgumentError, "subnetMask is required for static ip"
|
101
118
|
end
|
102
119
|
cust_ip_settings = RbVmomi::VIM::CustomizationIPSettings.new(
|
103
120
|
ip_settings
|
@@ -128,7 +145,7 @@ module ChefProvisioningVsphere
|
|
128
145
|
cust_hwclockutc = cust_options[:hw_clock_utc]
|
129
146
|
cust_timezone = cust_options[:time_zone]
|
130
147
|
|
131
|
-
cust_prep = if vm_template.config.guestId.start_with?(
|
148
|
+
cust_prep = if vm_template.config.guestId.start_with?("win")
|
132
149
|
windows_prep_for(options, vm_name)
|
133
150
|
else
|
134
151
|
RbVmomi::VIM::CustomizationLinuxPrep.new(
|
@@ -141,7 +158,7 @@ module ChefProvisioningVsphere
|
|
141
158
|
cust_adapter_mapping = [
|
142
159
|
RbVmomi::VIM::CustomizationAdapterMapping.new(
|
143
160
|
adapter: cust_ip_settings
|
144
|
-
)
|
161
|
+
),
|
145
162
|
]
|
146
163
|
RbVmomi::VIM::CustomizationSpec.new(
|
147
164
|
identity: cust_prep,
|
@@ -154,15 +171,23 @@ module ChefProvisioningVsphere
|
|
154
171
|
end
|
155
172
|
end
|
156
173
|
|
174
|
+
# Creates a hostname, and verifies that it fulfills the requirements
|
175
|
+
#
|
176
|
+
# @param [String] options Options set from Chef-Provisioning.
|
177
|
+
# @param [String] vm_name The VM name that is set.
|
157
178
|
def hostname_from(options, vm_name)
|
158
179
|
hostname = options[:hostname] || vm_name
|
159
180
|
test = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])$/
|
160
|
-
unless hostname
|
161
|
-
raise
|
181
|
+
unless hostname =~ test
|
182
|
+
raise "Only letters, numbers or hyphens in hostnames allowed"
|
162
183
|
end
|
163
184
|
RbVmomi::VIM::CustomizationFixedName.new(name: hostname)
|
164
185
|
end
|
165
186
|
|
187
|
+
# Preparation work for windows, sysprep and the like.
|
188
|
+
#
|
189
|
+
# @param [String] options Options set from Chef-Provisioning.
|
190
|
+
# @param [String] vm_name The VM name that is set.
|
166
191
|
def windows_prep_for(options, vm_name)
|
167
192
|
cust_options = options[:customization_spec]
|
168
193
|
unless cust_options[:run_once].nil?
|
@@ -175,22 +200,21 @@ module ChefProvisioningVsphere
|
|
175
200
|
plainText: true,
|
176
201
|
value: options[:ssh][:password]
|
177
202
|
)
|
178
|
-
if cust_options.key?(:domain) && (cust_options[:domain] !=
|
203
|
+
if cust_options.key?(:domain) && (cust_options[:domain] != "local")
|
179
204
|
cust_domain_password = RbVmomi::VIM::CustomizationPassword(
|
180
205
|
plainText: true,
|
181
|
-
value: ENV[
|
206
|
+
value: ENV["domainAdminPassword"] || cust_options[:domainAdminPassword]
|
182
207
|
)
|
183
208
|
cust_id = RbVmomi::VIM::CustomizationIdentification.new(
|
184
209
|
joinDomain: cust_options[:domain],
|
185
210
|
domainAdmin: cust_options[:domainAdmin],
|
186
211
|
domainAdminPassword: cust_domain_password
|
187
212
|
)
|
188
|
-
# puts "my env passwd is: #{ENV['domainAdminPassword']}"
|
189
213
|
action_handler.report_progress "joining domain #{cust_options[:domain]} /
|
190
214
|
with user: #{cust_options[:domainAdmin]}"
|
191
215
|
else
|
192
216
|
cust_id = RbVmomi::VIM::CustomizationIdentification.new(
|
193
|
-
joinWorkgroup:
|
217
|
+
joinWorkgroup: "WORKGROUP"
|
194
218
|
)
|
195
219
|
end
|
196
220
|
cust_gui_unattended = RbVmomi::VIM::CustomizationGuiUnattended.new(
|
@@ -1,20 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
|
2
|
+
require "chef"
|
3
|
+
require "cheffish/merged_config"
|
4
|
+
require "chef/provisioning/driver"
|
5
|
+
require "chef/provisioning/machine/windows_machine"
|
6
|
+
require "chef/provisioning/machine/unix_machine"
|
7
|
+
require "chef/provisioning/vsphere_driver/clone_spec_builder"
|
8
|
+
require "chef/provisioning/vsphere_driver/version"
|
9
|
+
require "chef/provisioning/vsphere_driver/vsphere_helpers"
|
10
|
+
require "chef/provisioning/vsphere_driver/vsphere_url"
|
11
|
+
require "chef/provisioning/vsphere_driver/vm_helper"
|
12
|
+
|
13
|
+
# Provisions machines in vSphere.
|
13
14
|
module ChefProvisioningVsphere
|
14
|
-
#
|
15
|
+
# Inherits the Chef::Provisioning::Driver attirbutes
|
15
16
|
class VsphereDriver < Chef::Provisioning::Driver
|
16
17
|
include Chef::Mixin::ShellOut
|
17
18
|
|
19
|
+
# Creates the new object via the URL
|
20
|
+
#
|
21
|
+
# @param [String] driver_url The driver url to connect via.
|
22
|
+
# @param [Object] config The config to get to the machine you are creating.
|
18
23
|
def self.from_url(driver_url, config)
|
19
24
|
VsphereDriver.new(driver_url, config)
|
20
25
|
end
|
@@ -34,6 +39,9 @@ module ChefProvisioningVsphere
|
|
34
39
|
[driver_url || URI::VsphereUrl.from_config(config).to_s, config]
|
35
40
|
end
|
36
41
|
|
42
|
+
# Converts the keys from strings to symbols
|
43
|
+
#
|
44
|
+
# @param [Object] h converts to key:value
|
37
45
|
def self.symbolize_keys(h)
|
38
46
|
Hash === h ?
|
39
47
|
Hash[
|
@@ -43,6 +51,9 @@ module ChefProvisioningVsphere
|
|
43
51
|
] : h
|
44
52
|
end
|
45
53
|
|
54
|
+
# Converts the keys from strings to symbols
|
55
|
+
#
|
56
|
+
# @param [Object] hash_like converts to key:value
|
46
57
|
def deep_symbolize(hash_like)
|
47
58
|
return {} if hash_like.nil? || hash_like.empty?
|
48
59
|
r = {}
|
@@ -53,17 +64,21 @@ module ChefProvisioningVsphere
|
|
53
64
|
r
|
54
65
|
end
|
55
66
|
|
67
|
+
# Initialize method for this class
|
68
|
+
#
|
69
|
+
# @param [String] driver_url Location of where the driver needs to connect to.
|
70
|
+
# @param [Object] config The complete config of the machine options.
|
56
71
|
def initialize(driver_url, config)
|
57
72
|
super(driver_url, config)
|
58
73
|
|
59
74
|
uri = URI(driver_url)
|
60
75
|
@connect_options = {
|
61
|
-
provider:
|
76
|
+
provider: "vsphere",
|
62
77
|
host: uri.host,
|
63
78
|
port: uri.port,
|
64
79
|
use_ssl: uri.use_ssl,
|
65
80
|
insecure: uri.insecure,
|
66
|
-
path: uri.path
|
81
|
+
path: uri.path,
|
67
82
|
}
|
68
83
|
|
69
84
|
if driver_options
|
@@ -74,6 +89,8 @@ module ChefProvisioningVsphere
|
|
74
89
|
|
75
90
|
attr_reader :connect_options, :vm_helper
|
76
91
|
|
92
|
+
# Creates a new vm_helper if not already there
|
93
|
+
#
|
77
94
|
def vm_helper
|
78
95
|
@vm_helper ||= ChefProvisioningVsphere::VmHelper.new
|
79
96
|
end
|
@@ -132,13 +149,13 @@ module ChefProvisioningVsphere
|
|
132
149
|
)
|
133
150
|
vm = vm_for(machine_spec)
|
134
151
|
if vm
|
135
|
-
Chef::Log.warn
|
152
|
+
Chef::Log.warn "returning existing machine"
|
136
153
|
return vm
|
137
154
|
else
|
138
155
|
Chef::Log.warn machine_msg(
|
139
156
|
machine_spec.name,
|
140
|
-
machine_spec.location[
|
141
|
-
|
157
|
+
machine_spec.location["server_id"],
|
158
|
+
"no longer exists. Recreating ..."
|
142
159
|
)
|
143
160
|
end
|
144
161
|
end
|
@@ -155,11 +172,14 @@ module ChefProvisioningVsphere
|
|
155
172
|
action_handler.performed_action(machine_msg(
|
156
173
|
machine_spec.name,
|
157
174
|
vm.config.instanceUuid,
|
158
|
-
|
175
|
+
"created"
|
159
176
|
))
|
160
177
|
vm
|
161
178
|
end
|
162
179
|
|
180
|
+
# Squishes the options to one large hash
|
181
|
+
#
|
182
|
+
# @param [Object] machine_options taken from Chef provisioning for all the `machine_options`
|
163
183
|
def merge_options!(machine_options)
|
164
184
|
@config = Cheffish::MergedConfig.new(
|
165
185
|
{ machine_options: machine_options },
|
@@ -168,17 +188,26 @@ module ChefProvisioningVsphere
|
|
168
188
|
@config = deep_symbolize(@config.to_h)
|
169
189
|
end
|
170
190
|
|
191
|
+
# Adds machine spec location from other options.
|
192
|
+
#
|
193
|
+
# @param [Object] machine_spec taken from Chef provisioning for all the `machine_spec`.
|
194
|
+
# @param [Object] vm taken from Chef provisioning for all the vm state.
|
171
195
|
def add_machine_spec_location(vm, machine_spec)
|
172
196
|
machine_spec.location = {
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
197
|
+
"driver_url" => driver_url,
|
198
|
+
"driver_version" => VERSION,
|
199
|
+
"server_id" => vm.config.instanceUuid,
|
200
|
+
"is_windows" => is_windows?(vm),
|
201
|
+
"allocated_at" => Time.now.utc.to_s,
|
202
|
+
"ipaddress" => vm.guest.ipAddress,
|
179
203
|
}
|
180
204
|
end
|
181
205
|
|
206
|
+
# Verify if machine is there or create it.
|
207
|
+
#
|
208
|
+
# @param [Object] bootstrap_options taken from Chef provisioning for all the bootstrap options.
|
209
|
+
# @param [Object] machine_spec taken from Chef provisioning for all the `machine_spec`.
|
210
|
+
# @param [Object] action_handler taken from Chef provisioning for TODO.
|
182
211
|
def find_or_create_vm(bootstrap_options, machine_spec, action_handler)
|
183
212
|
vm = vsphere_helper.find_vm(
|
184
213
|
bootstrap_options[:vm_folder],
|
@@ -188,7 +217,7 @@ module ChefProvisioningVsphere
|
|
188
217
|
Chef::Log.info machine_msg(
|
189
218
|
machine_spec.name,
|
190
219
|
vm.config.instanceUuid,
|
191
|
-
|
220
|
+
"already created"
|
192
221
|
)
|
193
222
|
else
|
194
223
|
vm = clone_vm(
|
@@ -200,12 +229,16 @@ module ChefProvisioningVsphere
|
|
200
229
|
vm
|
201
230
|
end
|
202
231
|
|
232
|
+
# Creates a full description of the machine.
|
233
|
+
#
|
234
|
+
# @param [Object] bootstrap_options taken from Chef provisioning for all the bootstrap options.
|
235
|
+
# @param [Object] machine_spec taken from Chef provisioning for all the `machine_spec`.
|
203
236
|
def full_description(machine_spec, bootstrap_options)
|
204
237
|
description = ["creating machine #{machine_spec.name} on #{driver_url}"]
|
205
238
|
bootstrap_options.to_hash.each_pair do |key, value|
|
206
239
|
if value.is_a?(Hash)
|
207
240
|
temp_value = value.clone
|
208
|
-
temp_value[:password] =
|
241
|
+
temp_value[:password] = "*********" if value.key?(:password)
|
209
242
|
else
|
210
243
|
temp_value = value
|
211
244
|
end
|
@@ -214,10 +247,21 @@ module ChefProvisioningVsphere
|
|
214
247
|
description
|
215
248
|
end
|
216
249
|
|
250
|
+
# Creates a string of specific Machine information
|
251
|
+
#
|
252
|
+
# @param [String] name The name of the machine
|
253
|
+
# @param [String] id The ID of the machine
|
254
|
+
# @param [Object] action TODO
|
255
|
+
# @return [String] "Machine - ACTION - NAME (UUID on URL)"
|
217
256
|
def machine_msg(name, id, action)
|
218
257
|
"Machine - #{action} - #{name} (#{id} on #{driver_url})"
|
219
258
|
end
|
220
259
|
|
260
|
+
# Sets the machine to ready state. (Creates the machine but does not bootstrap Chef into it.)
|
261
|
+
#
|
262
|
+
# @param [Object] action_handler TODO
|
263
|
+
# @param [Object] machine_options taken from Chef provisioning for all the bootstrap options.
|
264
|
+
# @param [Object] machine_spec taken from Chef provisioning for all the `machine_spec`.
|
221
265
|
def ready_machine(action_handler, machine_spec, machine_options)
|
222
266
|
machine_options = deep_symbolize(machine_options)
|
223
267
|
merge_options! machine_options
|
@@ -225,7 +269,7 @@ module ChefProvisioningVsphere
|
|
225
269
|
vm = start_machine(action_handler, machine_spec, machine_options)
|
226
270
|
if vm.nil?
|
227
271
|
raise "Machine #{machine_spec.name} does not have a server "\
|
228
|
-
|
272
|
+
"associated with it, or server does not exist."
|
229
273
|
end
|
230
274
|
|
231
275
|
bootstrap_options = machine_options[:bootstrap_options]
|
@@ -250,6 +294,12 @@ module ChefProvisioningVsphere
|
|
250
294
|
machine
|
251
295
|
end
|
252
296
|
|
297
|
+
# Creates new NICs for the machine
|
298
|
+
#
|
299
|
+
# @param [Object] action_handler TODO
|
300
|
+
# @param [Object] bootstrap_options taken from Chef provisioning for all the bootstrap options.
|
301
|
+
# @param [Object] vm The VM object.
|
302
|
+
# @param [Object] machine The machine object.
|
253
303
|
def setup_extra_nics(action_handler, bootstrap_options, vm, machine)
|
254
304
|
networks = bootstrap_options[:network_name]
|
255
305
|
networks = [networks] if networks.is_a?(String)
|
@@ -271,6 +321,12 @@ module ChefProvisioningVsphere
|
|
271
321
|
end
|
272
322
|
end
|
273
323
|
|
324
|
+
# Is the transport layer ready?
|
325
|
+
#
|
326
|
+
# @param [Object] action_handler TODO
|
327
|
+
# @param [Object] machine_spec taken from Chef provisioning for all the bootstrap options.
|
328
|
+
# @param [Object] vm The VM object.
|
329
|
+
# @param [Object] machine_options The options required to talk to the VM.
|
274
330
|
def transport_respond?(
|
275
331
|
machine_options,
|
276
332
|
vm,
|
@@ -284,7 +340,7 @@ module ChefProvisioningVsphere
|
|
284
340
|
# Customization below may change this to a valid ip
|
285
341
|
wait_until_ready(action_handler, machine_spec, machine_options, vm)
|
286
342
|
|
287
|
-
if !machine_spec.location[
|
343
|
+
if !machine_spec.location["ipaddress"] || !has_ip?(machine_spec.location["ipaddress"], vm)
|
288
344
|
# find the ip we actually want
|
289
345
|
# this will be the static ip to assign
|
290
346
|
# or the ip reported back by the vm if using dhcp
|
@@ -298,7 +354,7 @@ module ChefProvisioningVsphere
|
|
298
354
|
unless !transport.nil? && transport.available? && has_ip?(vm_ip, vm)
|
299
355
|
attempt_ip(machine_options, action_handler, vm, machine_spec)
|
300
356
|
end
|
301
|
-
machine_spec.location[
|
357
|
+
machine_spec.location["ipaddress"] = vm_ip # vm.guest.ipAddress vmWare ip_address here can be 0.0.0.0
|
302
358
|
action_handler.report_progress(
|
303
359
|
"IP address obtained: #{machine_spec.location['ipaddress']}"
|
304
360
|
)
|
@@ -310,14 +366,14 @@ module ChefProvisioningVsphere
|
|
310
366
|
wait_for_transport(action_handler, machine_spec, machine_options, vm)
|
311
367
|
rescue Timeout::Error
|
312
368
|
# Only ever reboot once, and only if it's been less than 10 minutes since we stopped waiting
|
313
|
-
if machine_spec.location[
|
314
|
-
|
369
|
+
if machine_spec.location["started_at"] ||
|
370
|
+
remaining_wait_time(machine_spec, machine_options) < -(10 * 60)
|
315
371
|
raise
|
316
372
|
else
|
317
373
|
Chef::Log.warn(machine_msg(
|
318
374
|
machine_spec.name,
|
319
375
|
vm.config.instanceUuid,
|
320
|
-
|
376
|
+
"started but SSH did not come up. Rebooting..."
|
321
377
|
))
|
322
378
|
restart_server(action_handler, machine_spec, machine_options)
|
323
379
|
wait_until_ready(action_handler, machine_spec, machine_options, vm)
|
@@ -326,19 +382,25 @@ module ChefProvisioningVsphere
|
|
326
382
|
end
|
327
383
|
end
|
328
384
|
|
385
|
+
# Test out the IP to connect to.
|
386
|
+
#
|
387
|
+
# @param [Object] action_handler TODO
|
388
|
+
# @param [Object] machine_options taken from Chef provisioning for all the bootstrap options.
|
389
|
+
# @param [Object] vm The VM object.
|
390
|
+
# @param [Object] machine_spec The spec required to talk to the VM.
|
329
391
|
def attempt_ip(machine_options, action_handler, vm, machine_spec)
|
330
392
|
vm_ip = ip_to_bootstrap(machine_options[:bootstrap_options], vm)
|
331
393
|
|
332
394
|
wait_for_ip(vm, machine_options, machine_spec, action_handler)
|
333
395
|
|
334
396
|
unless has_ip?(vm_ip, vm)
|
335
|
-
action_handler.report_progress
|
336
|
-
if vm.guest.toolsRunningStatus !=
|
337
|
-
msg =
|
397
|
+
action_handler.report_progress "rebooting..."
|
398
|
+
if vm.guest.toolsRunningStatus != "guestToolsRunning"
|
399
|
+
msg = "tools have stopped. current power state is "
|
338
400
|
msg << vm.runtime.powerState
|
339
|
-
msg <<
|
401
|
+
msg << " and tools state is "
|
340
402
|
msg << vm.guest.toolsRunningStatus
|
341
|
-
msg <<
|
403
|
+
msg << ". powering up server..."
|
342
404
|
action_handler.report_progress(msg)
|
343
405
|
vsphere_helper.start_vm(vm)
|
344
406
|
else
|
@@ -348,6 +410,12 @@ module ChefProvisioningVsphere
|
|
348
410
|
end
|
349
411
|
end
|
350
412
|
|
413
|
+
# Wait for the Windows Domain.
|
414
|
+
#
|
415
|
+
# @param [Object] action_handler TODO
|
416
|
+
# @param [Object] bootstrap_options taken from Chef provisioning for all the bootstrap options.
|
417
|
+
# @param [Object] vm The VM object.
|
418
|
+
# @param [Object] machine_spec The specs to connect to bootstrap machine
|
351
419
|
def wait_for_domain(bootstrap_options, vm, machine_spec, action_handler)
|
352
420
|
return unless bootstrap_options[:customization_spec]
|
353
421
|
|
@@ -363,7 +431,7 @@ module ChefProvisioningVsphere
|
|
363
431
|
|
364
432
|
return unless domain
|
365
433
|
|
366
|
-
if is_windows?(vm) && domain !=
|
434
|
+
if is_windows?(vm) && domain != "local"
|
367
435
|
start = Time.now.utc
|
368
436
|
trimmed_name = machine_spec.name.byteslice(0, 15)
|
369
437
|
expected_name = "#{trimmed_name}.#{domain}"
|
@@ -371,13 +439,19 @@ module ChefProvisioningVsphere
|
|
371
439
|
"waiting to domain join and be named #{expected_name}"
|
372
440
|
)
|
373
441
|
until (Time.now.utc - start) > 30 ||
|
374
|
-
|
375
|
-
print
|
442
|
+
(vm.guest.hostName == expected_name)
|
443
|
+
print "."
|
376
444
|
sleep 5
|
377
445
|
end
|
378
446
|
end
|
379
447
|
end
|
380
448
|
|
449
|
+
# Wait for another IP allocation.
|
450
|
+
#
|
451
|
+
# @param [Object] action_handler TODO
|
452
|
+
# @param [Object] vm The VM object.
|
453
|
+
# @param [Object] machine_options The machine options required to start the VM.
|
454
|
+
# @param [Object] machine_spec The machine spec required to start the VM.
|
381
455
|
def wait_for_ip(vm, machine_options, machine_spec, action_handler)
|
382
456
|
bootstrap_options = machine_options[:bootstrap_options]
|
383
457
|
ip_to_bootstrap(bootstrap_options, vm)
|
@@ -387,7 +461,7 @@ module ChefProvisioningVsphere
|
|
387
461
|
msg = [msg1, msg2].join
|
388
462
|
action_handler.report_progress msg
|
389
463
|
|
390
|
-
vm_ip
|
464
|
+
vm_ip = @vm_helper.ip || ip_to_bootstrap(bootstrap_options, vm)
|
391
465
|
until transport_for(
|
392
466
|
machine_spec,
|
393
467
|
machine_options[:bootstrap_options][:ssh],
|
@@ -396,7 +470,7 @@ module ChefProvisioningVsphere
|
|
396
470
|
action_handler.report_progress(
|
397
471
|
"IP addresses found: #{all_ips_for(vm)}"
|
398
472
|
)
|
399
|
-
vm_ip
|
473
|
+
vm_ip = @vm_helper.ip || ip_to_bootstrap(bootstrap_options, vm)
|
400
474
|
if has_ip?(vm_ip, vm)
|
401
475
|
transport_for(
|
402
476
|
machine_spec,
|
@@ -408,21 +482,36 @@ module ChefProvisioningVsphere
|
|
408
482
|
end
|
409
483
|
end
|
410
484
|
|
485
|
+
# Flatten all IPs for a VM
|
486
|
+
#
|
487
|
+
# @param [Object] vm The VM object.
|
411
488
|
def all_ips_for(vm)
|
412
489
|
vm.guest.net.map(&:ipAddress).flatten
|
413
490
|
end
|
414
491
|
|
492
|
+
# Does the VM have this IP?
|
493
|
+
#
|
494
|
+
# @param [Object] vm The VM object.
|
495
|
+
# @param [String] ip IP to see if it's in the map.
|
415
496
|
def has_ip?(ip, vm)
|
416
497
|
all_ips_for(vm).include?(ip)
|
417
498
|
end
|
418
499
|
|
419
500
|
# Connect to machine without acquiring it
|
501
|
+
#
|
502
|
+
# @param [Object] machine_options The machine options required to start the VM.
|
503
|
+
# @param [Object] machine_spec The machine spec required to start the VM.
|
420
504
|
def connect_to_machine(machine_spec, machine_options)
|
421
505
|
machine_options = deep_symbolize(machine_options)
|
422
506
|
merge_options! machine_options
|
423
507
|
machine_for(machine_spec, machine_options)
|
424
508
|
end
|
425
509
|
|
510
|
+
# Destroy the Machine
|
511
|
+
#
|
512
|
+
# @param [Object] machine_options The machine options required to start the VM.
|
513
|
+
# @param [Object] machine_spec The machine spec required to start the VM.
|
514
|
+
# @param [Object] action_handler TODO
|
426
515
|
def destroy_machine(action_handler, machine_spec, machine_options)
|
427
516
|
machine_options = deep_symbolize(machine_options)
|
428
517
|
merge_options! machine_options
|
@@ -433,7 +522,7 @@ module ChefProvisioningVsphere
|
|
433
522
|
vsphere_helper.stop_vm(vm, machine_options[:stop_timeout])
|
434
523
|
vm.Destroy_Task.wait_for_completion
|
435
524
|
rescue RbVmomi::Fault => fault
|
436
|
-
raise fault unless fault.fault.class.wsdl_name ==
|
525
|
+
raise fault unless fault.fault.class.wsdl_name == "ManagedObjectNotFound"
|
437
526
|
ensure
|
438
527
|
machine_spec.location = nil
|
439
528
|
end
|
@@ -443,6 +532,11 @@ module ChefProvisioningVsphere
|
|
443
532
|
strategy.cleanup_convergence(action_handler, machine_spec)
|
444
533
|
end
|
445
534
|
|
535
|
+
# Stop the Machine
|
536
|
+
#
|
537
|
+
# @param [Object] machine_options The machine options required to start the VM.
|
538
|
+
# @param [Object] machine_spec The machine spec required to start the VM.
|
539
|
+
# @param [Object] action_handler TODO
|
446
540
|
def stop_machine(action_handler, machine_spec, machine_options)
|
447
541
|
machine_options = deep_symbolize(machine_options)
|
448
542
|
merge_options! machine_options
|
@@ -454,6 +548,11 @@ module ChefProvisioningVsphere
|
|
454
548
|
end
|
455
549
|
end
|
456
550
|
|
551
|
+
# Start the Machine
|
552
|
+
#
|
553
|
+
# @param [Object] machine_options The machine options required to start the VM.
|
554
|
+
# @param [Object] machine_spec The machine spec required to start the VM.
|
555
|
+
# @param [Object] action_handler TODO
|
457
556
|
def start_machine(action_handler, machine_spec, machine_options)
|
458
557
|
machine_options = deep_symbolize(machine_options)
|
459
558
|
merge_options! machine_options
|
@@ -466,40 +565,53 @@ module ChefProvisioningVsphere
|
|
466
565
|
vm
|
467
566
|
end
|
468
567
|
|
568
|
+
# Restart the Machine
|
569
|
+
#
|
570
|
+
# @param [Object] machine_options The machine options required to start the VM.
|
571
|
+
# @param [Object] machine_spec The machine spec required to start the VM.
|
572
|
+
# @param [Object] action_handler TODO
|
469
573
|
def restart_server(action_handler, machine_spec, machine_options)
|
470
574
|
action_handler.perform_action "restart machine #{machine_spec.name} (#{driver_url})" do
|
471
575
|
stop_machine(action_handler, machine_spec, machine_options)
|
472
576
|
start_machine(action_handler, machine_spec, machine_options)
|
473
|
-
machine_spec.location[
|
577
|
+
machine_spec.location["started_at"] = Time.now.utc.to_s
|
474
578
|
end
|
475
579
|
end
|
476
580
|
|
477
581
|
protected
|
478
582
|
|
583
|
+
# Ubuntu requires some...hacking to get DNS to work.
|
584
|
+
#
|
585
|
+
# @param [Object] bootstrap_options The bootstarp options required to start the VM.
|
586
|
+
# @param [Object] _machine_spec The machine spec required to start the VM.
|
587
|
+
# @param [Object] machine Machine object to connect to.
|
479
588
|
def setup_ubuntu_dns(machine, bootstrap_options, _machine_spec)
|
480
|
-
host_lookup = machine.execute_always(
|
589
|
+
host_lookup = machine.execute_always("host google.com")
|
481
590
|
if host_lookup.exitstatus != 0
|
482
|
-
if host_lookup.stdout.include?(
|
483
|
-
machine.execute_always(
|
591
|
+
if host_lookup.stdout.include?("setlocale: LC_ALL")
|
592
|
+
machine.execute_always("locale-gen en_US && update-locale LANG=en_US")
|
484
593
|
end
|
485
594
|
distro = machine.execute_always("lsb_release -i | sed -e 's/Distributor ID://g'").stdout.strip
|
486
595
|
Chef::Log.info "Found distro:#{distro}"
|
487
|
-
if distro ==
|
488
|
-
distro_version = machine.execute_always(
|
596
|
+
if distro == "Ubuntu"
|
597
|
+
distro_version = machine.execute_always("lsb_release -r | sed -e s/[^0-9.]//g").stdout.strip.to_f
|
489
598
|
Chef::Log.info "Found distro version:#{distro_version}"
|
490
599
|
if distro_version >= 12.04
|
491
|
-
Chef::Log.info
|
492
|
-
interfaces_file =
|
493
|
-
nameservers = bootstrap_options[:customization_spec][:ipsettings][:dnsServerList].join(
|
600
|
+
Chef::Log.info "Ubuntu version 12.04 or greater. Need to patch DNS."
|
601
|
+
interfaces_file = "/etc/network/interfaces"
|
602
|
+
nameservers = bootstrap_options[:customization_spec][:ipsettings][:dnsServerList].join(" ")
|
494
603
|
machine.execute_always("if ! cat #{interfaces_file} | grep -q dns-search ; then echo 'dns-search #{bootstrap_options[:customization_spec][:domain]}' >> #{interfaces_file} ; fi")
|
495
604
|
machine.execute_always("if ! cat #{interfaces_file} | grep -q dns-nameservers ; then echo 'dns-nameservers #{nameservers}' >> #{interfaces_file} ; fi")
|
496
|
-
machine.execute_always(
|
497
|
-
machine.execute_always(
|
605
|
+
machine.execute_always("/etc/init.d/networking restart")
|
606
|
+
machine.execute_always("apt-get -qq update")
|
498
607
|
end
|
499
608
|
end
|
500
609
|
end
|
501
610
|
end
|
502
611
|
|
612
|
+
# Verify static IP.
|
613
|
+
#
|
614
|
+
# @param [Object] bootstrap_options The bootstarp options required to start the VM.
|
503
615
|
def has_static_ip(bootstrap_options)
|
504
616
|
if bootstrap_options.key?(:customization_spec)
|
505
617
|
bootstrap_options = bootstrap_options[:customization_spec]
|
@@ -516,22 +628,22 @@ module ChefProvisioningVsphere
|
|
516
628
|
end
|
517
629
|
|
518
630
|
def remaining_wait_time(machine_spec, machine_options)
|
519
|
-
if machine_spec.location[
|
631
|
+
if machine_spec.location["started_at"]
|
520
632
|
(machine_options[:start_timeout] || 600) -
|
521
|
-
(Time.now.utc - Time.parse(machine_spec.location[
|
633
|
+
(Time.now.utc - Time.parse(machine_spec.location["started_at"]))
|
522
634
|
else
|
523
635
|
(machine_options[:create_timeout] || 600) -
|
524
|
-
(Time.now.utc - Time.parse(machine_spec.location[
|
636
|
+
(Time.now.utc - Time.parse(machine_spec.location["allocated_at"]))
|
525
637
|
end
|
526
638
|
end
|
527
639
|
|
528
640
|
def wait_until_ready(action_handler, machine_spec, machine_options, vm)
|
529
|
-
if vm.guest.toolsRunningStatus !=
|
641
|
+
if vm.guest.toolsRunningStatus != "guestToolsRunning"
|
530
642
|
if action_handler.should_perform_actions
|
531
643
|
action_handler.report_progress "waiting for #{machine_spec.name} (#{vm.config.instanceUuid} on #{driver_url}) to be ready ..."
|
532
644
|
until remaining_wait_time(machine_spec, machine_options) < 0 ||
|
533
|
-
|
534
|
-
print
|
645
|
+
(vm.guest.toolsRunningStatus == "guestToolsRunning" && vm.guest.ipAddress && !vm.guest.ipAddress.empty?)
|
646
|
+
print "."
|
535
647
|
sleep 5
|
536
648
|
end
|
537
649
|
action_handler.report_progress "#{machine_spec.name} is now ready"
|
@@ -541,7 +653,7 @@ module ChefProvisioningVsphere
|
|
541
653
|
|
542
654
|
def vm_for(machine_spec)
|
543
655
|
if machine_spec.location
|
544
|
-
vsphere_helper.find_vm_by_id(machine_spec.location[
|
656
|
+
vsphere_helper.find_vm_by_id(machine_spec.location["server_id"])
|
545
657
|
end
|
546
658
|
end
|
547
659
|
|
@@ -570,7 +682,7 @@ module ChefProvisioningVsphere
|
|
570
682
|
size = size.to_i
|
571
683
|
next if size == 0
|
572
684
|
if bootstrap_options[:datastore].to_s.empty?
|
573
|
-
raise
|
685
|
+
raise ":datastore must be specified when adding a disk to a cloned vm"
|
574
686
|
end
|
575
687
|
task = vm.ReconfigVM_Task(
|
576
688
|
spec: RbVmomi::VIM.VirtualMachineConfigSpec(
|
@@ -579,7 +691,7 @@ module ChefProvisioningVsphere
|
|
579
691
|
vm,
|
580
692
|
bootstrap_options[:datastore],
|
581
693
|
size
|
582
|
-
)
|
694
|
+
),
|
583
695
|
]
|
584
696
|
)
|
585
697
|
)
|
@@ -614,7 +726,7 @@ module ChefProvisioningVsphere
|
|
614
726
|
)
|
615
727
|
strategy = convergence_strategy_for(machine_spec, machine_options)
|
616
728
|
|
617
|
-
if machine_spec.location[
|
729
|
+
if machine_spec.location["is_windows"]
|
618
730
|
Chef::Provisioning::Machine::WindowsMachine.new(
|
619
731
|
machine_spec, transport, strategy
|
620
732
|
)
|
@@ -627,13 +739,13 @@ module ChefProvisioningVsphere
|
|
627
739
|
|
628
740
|
def is_windows?(vm)
|
629
741
|
return false if vm.nil?
|
630
|
-
vm.config.guestId.start_with?(
|
742
|
+
vm.config.guestId.start_with?("win")
|
631
743
|
end
|
632
744
|
|
633
745
|
def convergence_strategy_for(machine_spec, machine_options)
|
634
|
-
require
|
635
|
-
require
|
636
|
-
require
|
746
|
+
require "chef/provisioning/convergence_strategy/install_msi"
|
747
|
+
require "chef/provisioning/convergence_strategy/install_cached"
|
748
|
+
require "chef/provisioning/convergence_strategy/no_converge"
|
637
749
|
|
638
750
|
mopts = machine_options[:convergence_options].to_hash.dup
|
639
751
|
if mopts[:chef_server]
|
@@ -647,7 +759,7 @@ module ChefProvisioningVsphere
|
|
647
759
|
)
|
648
760
|
end
|
649
761
|
|
650
|
-
if machine_spec.location[
|
762
|
+
if machine_spec.location["is_windows"]
|
651
763
|
Chef::Provisioning::ConvergenceStrategy::InstallMsi.new(
|
652
764
|
mopts, config
|
653
765
|
)
|
@@ -658,6 +770,12 @@ module ChefProvisioningVsphere
|
|
658
770
|
end
|
659
771
|
end
|
660
772
|
|
773
|
+
# Wait for the transport connection to happen
|
774
|
+
#
|
775
|
+
# @param [Object] machine_spec The machine_spec from Chef-Provisioning
|
776
|
+
# @param [Object] machine_options Options for remote connections
|
777
|
+
# @param [Object] vm The VM object from Chef-Provisioning
|
778
|
+
# @param [Object] action_handler taken from Chef provisioning for TODO.
|
661
779
|
def wait_for_transport(action_handler, machine_spec, machine_options, vm)
|
662
780
|
@vm_helper.find_port?(vm, machine_options[:bootstrap_options]) if vm_helper.port.nil?
|
663
781
|
transport = transport_for(
|
@@ -669,7 +787,7 @@ module ChefProvisioningVsphere
|
|
669
787
|
action_handler.report_progress "waiting for #{machine_spec.name} (#{vm.config.instanceUuid} on #{driver_url}) to be connectable (transport up and running) ..."
|
670
788
|
|
671
789
|
until remaining_wait_time(machine_spec, machine_options) < 0 || transport.available?
|
672
|
-
print
|
790
|
+
print "."
|
673
791
|
sleep 5
|
674
792
|
end
|
675
793
|
|
@@ -678,29 +796,38 @@ module ChefProvisioningVsphere
|
|
678
796
|
end
|
679
797
|
end
|
680
798
|
|
799
|
+
# Figure out the transport system to send to the VM
|
800
|
+
#
|
801
|
+
# @param [Object] machine_spec The machine_spec from Chef-Provisioning
|
802
|
+
# @param [Object] remoting_options Options for remote connections
|
803
|
+
# @param [String] ip The IP to connect to.
|
681
804
|
def transport_for(
|
682
805
|
machine_spec,
|
683
806
|
remoting_options,
|
684
|
-
ip = machine_spec.location[
|
807
|
+
ip = machine_spec.location["ipaddress"]
|
685
808
|
)
|
686
|
-
if machine_spec.location[
|
809
|
+
if machine_spec.location["is_windows"]
|
687
810
|
create_winrm_transport(ip, remoting_options)
|
688
811
|
else
|
689
812
|
create_ssh_transport(ip, remoting_options)
|
690
813
|
end
|
691
814
|
end
|
692
815
|
|
816
|
+
# Create a robust WinRM transport connect, so so many options to make a simple connection
|
817
|
+
#
|
818
|
+
# @param [String] host The host the VM is connecting to
|
819
|
+
# @param [Object] options Options that are required to connect to the host from Chef-Provisioning
|
693
820
|
def create_winrm_transport(host, options)
|
694
|
-
require
|
821
|
+
require "chef/provisioning/transport/winrm"
|
695
822
|
winrm_transport = if options[:port] == 5986
|
696
823
|
:ssl
|
697
824
|
else
|
698
825
|
options[:winrm_transport].nil? ? :negotiate : options[:winrm_transport].to_sym
|
699
826
|
end
|
700
|
-
port = options[:port] || @vm_helper.port
|
827
|
+
port = options[:port] || @vm_helper.port
|
701
828
|
winrm_options = {
|
702
829
|
user: (options[:user]).to_s,
|
703
|
-
pass: options[:password]
|
830
|
+
pass: options[:password],
|
704
831
|
}
|
705
832
|
if options[:winrm_opts].nil?
|
706
833
|
opt = options[:user].include?('\\') ? :disable_sspi : :basic_auth_only
|
@@ -719,30 +846,37 @@ module ChefProvisioningVsphere
|
|
719
846
|
)
|
720
847
|
end
|
721
848
|
|
849
|
+
# Find the IP to bootstrap against
|
850
|
+
#
|
851
|
+
# @param [String] host The host the VM is connecting to
|
852
|
+
# @param [Object] options Options that are required to connect to the host from Chef-Provisioning
|
722
853
|
def create_ssh_transport(host, options)
|
723
|
-
require
|
854
|
+
require "chef/provisioning/transport/ssh"
|
724
855
|
ssh_user = options[:user]
|
725
856
|
options = options.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v; }
|
726
857
|
Chef::Provisioning::Transport::SSH.new(
|
727
858
|
host,
|
728
859
|
ssh_user,
|
729
860
|
options.to_hash,
|
730
|
-
@config[:machine_options][:sudo] ? { prefix:
|
861
|
+
@config[:machine_options][:sudo] ? { prefix: "sudo " } : {},
|
731
862
|
config
|
732
863
|
)
|
733
864
|
end
|
734
865
|
|
866
|
+
# Find the IP to bootstrap against
|
867
|
+
#
|
868
|
+
# @param [Object] bootstrap_options The bootstrap options from Chef-Provisioning
|
869
|
+
# @param [Object] vm The VM object from Chef-Provisioning
|
735
870
|
def ip_to_bootstrap(bootstrap_options, vm)
|
736
871
|
@vm_helper.find_port?(vm, bootstrap_options) unless vm_helper.port?
|
737
872
|
if has_static_ip(bootstrap_options)
|
738
873
|
if bootstrap_options[:customization_spec].is_a?(String)
|
739
874
|
spec = vsphere_helper.find_customization_spec(bootstrap_options[:customization_spec])
|
740
|
-
spec.nicSettingMap[0].adapter.ip.ipAddress
|
875
|
+
@vm_helper.ip = spec.nicSettingMap[0].adapter.ip.ipAddress
|
741
876
|
else
|
742
877
|
## Check if true available
|
743
878
|
@vm_helper.ip = bootstrap_options[:customization_spec][:ipsettings][:ip] unless vm_helper.ip?
|
744
|
-
print
|
745
|
-
@vm_helper.ip.to_s
|
879
|
+
print "." until @vm_helper.open_port?(@vm_helper.ip, @vm_helper.port, 1)
|
746
880
|
end
|
747
881
|
else
|
748
882
|
if use_ipv4_during_bootstrap?(bootstrap_options)
|
@@ -751,10 +885,13 @@ module ChefProvisioningVsphere
|
|
751
885
|
end
|
752
886
|
end
|
753
887
|
@vm_helper.ip = vm.guest.ipAddress until vm_guest_ip?(vm) && @vm_helper.open_port?(@vm_helper.ip, @vm_helper.port, 1) # Don't set empty ip
|
754
|
-
@vm_helper.ip
|
755
888
|
end
|
889
|
+
@vm_helper.ip.to_s
|
756
890
|
end
|
757
891
|
|
892
|
+
# Force IPv4 a bootstrap, default: false
|
893
|
+
#
|
894
|
+
# @param [Object] bootstrap_options The bootstrap options from Chef-Provisioning
|
758
895
|
def use_ipv4_during_bootstrap?(bootstrap_options)
|
759
896
|
if bootstrap_options.key?(:bootstrap_ipv4)
|
760
897
|
return bootstrap_options[:bootstrap_ipv4] == true
|
@@ -762,6 +899,9 @@ module ChefProvisioningVsphere
|
|
762
899
|
false
|
763
900
|
end
|
764
901
|
|
902
|
+
# Setting a bootstrap ip timeout, default: 30
|
903
|
+
#
|
904
|
+
# @param [Object] bootstrap_options The bootstrap options from Chef-Provisioning
|
765
905
|
def bootstrap_ip_timeout(bootstrap_options)
|
766
906
|
if bootstrap_options.key?(:ipv4_timeout)
|
767
907
|
return bootstrap_options[:ipv4_timeout].to_i
|
@@ -769,25 +909,32 @@ module ChefProvisioningVsphere
|
|
769
909
|
30
|
770
910
|
end
|
771
911
|
|
912
|
+
# What for IPv4 address
|
913
|
+
#
|
914
|
+
# @param [String] timeout Declared a timeout
|
915
|
+
# @param [Object] vm The VM object from Chef-Provisioning
|
772
916
|
def wait_for_ipv4(timeout, vm)
|
773
917
|
sleep_time = 5
|
774
|
-
print
|
918
|
+
print "Waiting for ipv4 address."
|
775
919
|
tries = 0
|
776
920
|
start_search_ip = true
|
777
921
|
max_tries = timeout > sleep_time ? timeout / sleep_time : 1
|
778
922
|
while start_search_ip && (tries += 1) <= max_tries
|
779
|
-
print
|
923
|
+
print "."
|
780
924
|
sleep sleep_time
|
781
925
|
@vm_helper.ip = vm.guest.ipAddress if vm_guest_ip?(vm)
|
782
926
|
start_search_ip = false if @vm_helper.open_port?(@vm_helper.ip, @vm_helper.port, 1)
|
783
927
|
end
|
784
|
-
raise
|
785
|
-
puts
|
928
|
+
raise "Timed out waiting for ipv4 address!" if tries > max_tries && !IPAddr.new(vm.guest.ipAddress).ipv4?
|
929
|
+
puts "Found ipv4 address!"
|
786
930
|
true
|
787
931
|
end
|
788
932
|
|
933
|
+
# What is the VM guest IP
|
934
|
+
#
|
935
|
+
# @param [Object] vm The VM object from Chef-Provisioning
|
789
936
|
def vm_guest_ip?(vm)
|
790
|
-
vm.guest.guestState ==
|
937
|
+
vm.guest.guestState == "running" && vm.guest.toolsRunningStatus == "guestToolsRunning" && !vm.guest.ipAddress.nil? && IPAddr.new(vm.guest.ipAddress).ipv4?
|
791
938
|
end
|
792
939
|
end
|
793
940
|
end
|