djo-vagrant-vsphere 1.6.1
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 +7 -0
- data/.bumpversion.cfg +11 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +13 -0
- data/.rubocop_todo.yml +80 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +250 -0
- data/DEVELOPMENT.md +67 -0
- data/Gemfile +16 -0
- data/LICENSE.txt +24 -0
- data/README.md +310 -0
- data/Rakefile +20 -0
- data/example_box/metadata.json +3 -0
- data/lib/vSphere/action.rb +195 -0
- data/lib/vSphere/action/clone.rb +239 -0
- data/lib/vSphere/action/close_vsphere.rb +22 -0
- data/lib/vSphere/action/connect_vsphere.rb +29 -0
- data/lib/vSphere/action/destroy.rb +41 -0
- data/lib/vSphere/action/get_ssh_info.rb +37 -0
- data/lib/vSphere/action/get_state.rb +41 -0
- data/lib/vSphere/action/is_created.rb +16 -0
- data/lib/vSphere/action/is_running.rb +16 -0
- data/lib/vSphere/action/message_already_created.rb +18 -0
- data/lib/vSphere/action/message_not_created.rb +18 -0
- data/lib/vSphere/action/message_not_running.rb +18 -0
- data/lib/vSphere/action/power_off.rb +40 -0
- data/lib/vSphere/action/power_on.rb +28 -0
- data/lib/vSphere/cap/public_address.rb +15 -0
- data/lib/vSphere/config.rb +60 -0
- data/lib/vSphere/errors.rb +11 -0
- data/lib/vSphere/plugin.rb +44 -0
- data/lib/vSphere/provider.rb +39 -0
- data/lib/vSphere/util/vim_helpers.rb +91 -0
- data/lib/vSphere/util/vm_helpers.rb +39 -0
- data/lib/vSphere/version.rb +5 -0
- data/lib/vagrant-vsphere.rb +18 -0
- data/locales/en.yml +64 -0
- data/spec/action_spec.rb +162 -0
- data/spec/clone_spec.rb +102 -0
- data/spec/connect_vsphere_spec.rb +26 -0
- data/spec/destroy_spec.rb +31 -0
- data/spec/get_ssh_info_spec.rb +31 -0
- data/spec/get_state_spec.rb +55 -0
- data/spec/is_created_spec.rb +29 -0
- data/spec/power_off_spec.rb +35 -0
- data/spec/spec_helper.rb +147 -0
- data/vSphere.gemspec +30 -0
- data/vsphere_screenshot.png +0 -0
- metadata +212 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
module Action
|
6
|
+
class MessageAlreadyCreated
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:ui].info I18n.t('vsphere.vm_already_created')
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
module Action
|
6
|
+
class MessageNotCreated
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:ui].info I18n.t('vsphere.vm_not_created')
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'i18n'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
module Action
|
6
|
+
class MessageNotRunning
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[:ui].info I18n.t('vsphere.vm_not_running')
|
13
|
+
@app.call(env)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
require 'i18n'
|
3
|
+
require 'vSphere/util/vim_helpers'
|
4
|
+
require 'vSphere/util/vm_helpers'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module VSphere
|
8
|
+
module Action
|
9
|
+
class PowerOff
|
10
|
+
include Util::VimHelpers
|
11
|
+
include Util::VmHelpers
|
12
|
+
|
13
|
+
def initialize(app, _env)
|
14
|
+
@app = app
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
vm = get_vm_by_uuid env[:vSphere_connection], env[:machine]
|
19
|
+
|
20
|
+
# If the vm is suspended, we need to turn it on so that we can turn it off.
|
21
|
+
# This may seem counterintuitive, but the vsphere API documentation states
|
22
|
+
# that the Power Off task for a VM will fail if the state is not poweredOn
|
23
|
+
# see: https://www.vmware.com/support/developer/vc-sdk/visdk41pubs/ApiReference/vim.VirtualMachine.html#powerOff
|
24
|
+
if suspended?(vm)
|
25
|
+
env[:ui].info I18n.t('vsphere.power_on_vm')
|
26
|
+
power_on_vm(vm)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Powering off is a no-op if we can't find the VM or if it is already off
|
30
|
+
unless vm.nil? || powered_off?(vm)
|
31
|
+
env[:ui].info I18n.t('vsphere.power_off_vm')
|
32
|
+
power_off_vm(vm)
|
33
|
+
end
|
34
|
+
|
35
|
+
@app.call env
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
require 'i18n'
|
3
|
+
require 'vSphere/util/vim_helpers'
|
4
|
+
require 'vSphere/util/vm_helpers'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module VSphere
|
8
|
+
module Action
|
9
|
+
class PowerOn
|
10
|
+
include Util::VimHelpers
|
11
|
+
include Util::VmHelpers
|
12
|
+
|
13
|
+
def initialize(app, _env)
|
14
|
+
@app = app
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(env)
|
18
|
+
vm = get_vm_by_uuid env[:vSphere_connection], env[:machine]
|
19
|
+
|
20
|
+
env[:ui].info I18n.t('vsphere.power_on_vm')
|
21
|
+
power_on_vm(vm)
|
22
|
+
|
23
|
+
@app.call env
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module VagrantPlugins
|
2
|
+
module VSphere
|
3
|
+
module Cap
|
4
|
+
module PublicAddress
|
5
|
+
def self.public_address(machine)
|
6
|
+
return nil if machine.state.id != :running
|
7
|
+
|
8
|
+
ssh_info = machine.ssh_info
|
9
|
+
return nil unless ssh_info
|
10
|
+
ssh_info[:host]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
class Config < Vagrant.plugin('2', :config)
|
6
|
+
attr_accessor :host
|
7
|
+
attr_accessor :insecure
|
8
|
+
attr_accessor :user
|
9
|
+
attr_accessor :password
|
10
|
+
attr_accessor :data_center_name
|
11
|
+
attr_accessor :compute_resource_name
|
12
|
+
attr_accessor :resource_pool_name
|
13
|
+
attr_accessor :clone_from_vm
|
14
|
+
attr_accessor :template_name
|
15
|
+
attr_accessor :name
|
16
|
+
attr_accessor :vm_base_path
|
17
|
+
attr_accessor :customization_spec_name
|
18
|
+
attr_accessor :data_store_name
|
19
|
+
attr_accessor :linked_clone
|
20
|
+
attr_accessor :proxy_host
|
21
|
+
attr_accessor :proxy_port
|
22
|
+
attr_accessor :vlan
|
23
|
+
attr_accessor :addressType
|
24
|
+
attr_accessor :mac
|
25
|
+
attr_accessor :memory_mb
|
26
|
+
attr_accessor :cpu_count
|
27
|
+
attr_accessor :cpu_reservation
|
28
|
+
attr_accessor :mem_reservation
|
29
|
+
|
30
|
+
attr_reader :custom_attributes
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@custom_attributes = {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def custom_attribute(key, value)
|
37
|
+
@custom_attributes[key.to_sym] = value
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate(machine)
|
41
|
+
errors = _detected_errors
|
42
|
+
|
43
|
+
if password == :ask || password.nil?
|
44
|
+
self.password = machine.ui.ask('vSphere Password (will be hidden): ', echo: false)
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO: add blank?
|
48
|
+
errors << I18n.t('vsphere.config.host') if host.nil?
|
49
|
+
errors << I18n.t('vsphere.config.user') if user.nil?
|
50
|
+
errors << I18n.t('vsphere.config.password') if password.nil?
|
51
|
+
errors << I18n.t('vsphere.config.template') if template_name.nil?
|
52
|
+
|
53
|
+
# Only required if we're cloning from an actual template
|
54
|
+
errors << I18n.t('vsphere.config.compute_resource') if compute_resource_name.nil? && !clone_from_vm
|
55
|
+
|
56
|
+
{ 'vSphere Provider' => errors }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
begin
|
2
|
+
require 'vagrant'
|
3
|
+
rescue LoadError
|
4
|
+
raise 'The Vagrant vSphere plugin must be run within Vagrant.'
|
5
|
+
end
|
6
|
+
|
7
|
+
# This is a sanity check to make sure no one is attempting to install
|
8
|
+
# this into an early Vagrant version.
|
9
|
+
if Vagrant::VERSION < '1.5'
|
10
|
+
fail 'The Vagrant vSphere plugin is only compatible with Vagrant 1.5+'
|
11
|
+
end
|
12
|
+
|
13
|
+
module VagrantPlugins
|
14
|
+
module VSphere
|
15
|
+
class Plugin < Vagrant.plugin('2')
|
16
|
+
name 'vsphere'
|
17
|
+
description 'Allows Vagrant to manage machines with VMWare vSphere'
|
18
|
+
|
19
|
+
config(:vsphere, :provider) do
|
20
|
+
require_relative 'config'
|
21
|
+
Config
|
22
|
+
end
|
23
|
+
|
24
|
+
provider(:vsphere, parallel: true) do
|
25
|
+
# TODO: add logging
|
26
|
+
setup_i18n
|
27
|
+
|
28
|
+
# Return the provider
|
29
|
+
require_relative 'provider'
|
30
|
+
Provider
|
31
|
+
end
|
32
|
+
|
33
|
+
provider_capability('vsphere', 'public_address') do
|
34
|
+
require_relative 'cap/public_address'
|
35
|
+
Cap::PublicAddress
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.setup_i18n
|
39
|
+
I18n.load_path << File.expand_path('locales/en.yml', VSphere.source_root)
|
40
|
+
I18n.reload!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
class Provider < Vagrant.plugin('2', :provider)
|
6
|
+
def initialize(machine)
|
7
|
+
@machine = machine
|
8
|
+
end
|
9
|
+
|
10
|
+
def action(name)
|
11
|
+
action_method = "action_#{name}"
|
12
|
+
return Action.send(action_method) if Action.respond_to?(action_method)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def ssh_info
|
17
|
+
env = @machine.action('get_ssh_info')
|
18
|
+
env[:machine_ssh_info]
|
19
|
+
end
|
20
|
+
|
21
|
+
def state
|
22
|
+
env = @machine.action('get_state')
|
23
|
+
|
24
|
+
state_id = env[:machine_state_id]
|
25
|
+
|
26
|
+
short = "vagrant_vsphere.states.short_#{state_id}"
|
27
|
+
long = "vagrant_vsphere.states.long_#{state_id}"
|
28
|
+
|
29
|
+
# Return the MachineState object
|
30
|
+
Vagrant::MachineState.new(state_id, short, long)
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
id = @machine.id.nil? ? 'new' : @machine.id
|
35
|
+
"vSphere (#{id})"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
module Util
|
6
|
+
module VimHelpers
|
7
|
+
def get_datacenter(connection, machine)
|
8
|
+
connection.serviceInstance.find_datacenter(machine.provider_config.data_center_name) || fail(Errors::VSphereError, :missing_datacenter)
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_vm_by_uuid(connection, machine)
|
12
|
+
get_datacenter(connection, machine).vmFolder.findByUuid machine.id
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_resource_pool(datacenter, machine)
|
16
|
+
compute_resource = get_compute_resource(datacenter, machine)
|
17
|
+
rp = compute_resource.resourcePool
|
18
|
+
unless machine.provider_config.resource_pool_name.nil?
|
19
|
+
rp = compute_resource.resourcePool.find(machine.provider_config.resource_pool_name)
|
20
|
+
fail Errors::VSphereError, :missing_resource_pool if rp.nil?
|
21
|
+
end
|
22
|
+
rp
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_compute_resource(datacenter, machine)
|
26
|
+
cr = find_clustercompute_or_compute_resource(datacenter, machine.provider_config.compute_resource_name)
|
27
|
+
fail Errors::VSphereError, :missing_compute_resource if cr.nil?
|
28
|
+
cr
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_clustercompute_or_compute_resource(datacenter, path)
|
32
|
+
if path.is_a? String
|
33
|
+
es = path.split('/').reject(&:empty?)
|
34
|
+
elsif path.is_a? Enumerable
|
35
|
+
es = path
|
36
|
+
else
|
37
|
+
fail "unexpected path class #{path.class}"
|
38
|
+
end
|
39
|
+
return datacenter.hostFolder if es.empty?
|
40
|
+
final = es.pop
|
41
|
+
|
42
|
+
p = es.inject(datacenter.hostFolder) do |f, e|
|
43
|
+
f.find(e, RbVmomi::VIM::Folder) || return
|
44
|
+
end
|
45
|
+
|
46
|
+
begin
|
47
|
+
if (x = p.find(final, RbVmomi::VIM::ComputeResource))
|
48
|
+
x
|
49
|
+
elsif (x = p.find(final, RbVmomi::VIM::ClusterComputeResource))
|
50
|
+
x
|
51
|
+
end
|
52
|
+
rescue Exception
|
53
|
+
# When looking for the ClusterComputeResource there seems to be some parser error in RbVmomi Folder.find, try this instead
|
54
|
+
x = p.childEntity.find { |x2| x2.name == final }
|
55
|
+
if x.is_a?(RbVmomi::VIM::ClusterComputeResource) || x.is_a?(RbVmomi::VIM::ComputeResource)
|
56
|
+
x
|
57
|
+
else
|
58
|
+
puts 'ex unknown type ' + x.to_json
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_customization_spec_info_by_name(connection, machine)
|
65
|
+
name = machine.provider_config.customization_spec_name
|
66
|
+
return if name.nil? || name.empty?
|
67
|
+
|
68
|
+
manager = connection.serviceContent.customizationSpecManager
|
69
|
+
fail Errors::VSphereError, :null_configuration_spec_manager if manager.nil?
|
70
|
+
|
71
|
+
spec = manager.GetCustomizationSpec(name: name)
|
72
|
+
fail Errors::VSphereError, :missing_configuration_spec if spec.nil?
|
73
|
+
|
74
|
+
spec
|
75
|
+
end
|
76
|
+
|
77
|
+
def get_datastore(datacenter, machine)
|
78
|
+
name = machine.provider_config.data_store_name
|
79
|
+
return if name.nil? || name.empty?
|
80
|
+
|
81
|
+
# find_datastore uses folder datastore that only lists Datastore and not StoragePod, if not found also try datastoreFolder which contains StoragePod(s)
|
82
|
+
datacenter.find_datastore(name) || datacenter.datastoreFolder.traverse(name) || fail(Errors::VSphereError, :missing_datastore)
|
83
|
+
end
|
84
|
+
|
85
|
+
def get_network_by_name(dc, name)
|
86
|
+
dc.network.find { |f| f.name == name } || fail(Errors::VSphereError, :missing_vlan)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rbvmomi'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module VSphere
|
5
|
+
module Util
|
6
|
+
module VmState
|
7
|
+
POWERED_ON = 'poweredOn'
|
8
|
+
POWERED_OFF = 'poweredOff'
|
9
|
+
SUSPENDED = 'suspended'
|
10
|
+
end
|
11
|
+
|
12
|
+
module VmHelpers
|
13
|
+
def power_on_vm(vm)
|
14
|
+
vm.PowerOnVM_Task.wait_for_completion
|
15
|
+
end
|
16
|
+
|
17
|
+
def power_off_vm(vm)
|
18
|
+
vm.PowerOffVM_Task.wait_for_completion
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_vm_state(vm)
|
22
|
+
vm.runtime.powerState
|
23
|
+
end
|
24
|
+
|
25
|
+
def powered_on?(vm)
|
26
|
+
get_vm_state(vm).eql?(VmState::POWERED_ON)
|
27
|
+
end
|
28
|
+
|
29
|
+
def powered_off?(vm)
|
30
|
+
get_vm_state(vm).eql?(VmState::POWERED_OFF)
|
31
|
+
end
|
32
|
+
|
33
|
+
def suspended?(vm)
|
34
|
+
get_vm_state(vm).eql?(VmState::SUSPENDED)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|