chef-provisioning-vsphere 2.0.2 → 2.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.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]
|
4
4
|
[][travis]
|
5
|
+
[](http://inch-ci.org/github/chef-partners/chef-provisioning-vsphere)
|
6
|
+
[](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
|