vagrant-vmware-esxi 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +14 -0
- data/LICENSE +674 -0
- data/README.md +175 -0
- data/Rakefile +4 -0
- data/example_box/metadata.json +4 -0
- data/lib/vagrant-vmware-esxi.rb +18 -0
- data/lib/vagrant-vmware-esxi/action.rb +119 -0
- data/lib/vagrant-vmware-esxi/action/boot.rb +59 -0
- data/lib/vagrant-vmware-esxi/action/connect_esxi.rb +58 -0
- data/lib/vagrant-vmware-esxi/action/createvm.rb +302 -0
- data/lib/vagrant-vmware-esxi/action/destroy.rb +58 -0
- data/lib/vagrant-vmware-esxi/action/halt.rb +52 -0
- data/lib/vagrant-vmware-esxi/action/read_ssh_info.rb +63 -0
- data/lib/vagrant-vmware-esxi/action/read_state.rb +67 -0
- data/lib/vagrant-vmware-esxi/action/resume.rb +63 -0
- data/lib/vagrant-vmware-esxi/action/suspend.rb +61 -0
- data/lib/vagrant-vmware-esxi/action/wait_for_state.rb +40 -0
- data/lib/vagrant-vmware-esxi/config.rb +56 -0
- data/lib/vagrant-vmware-esxi/errors.rb +22 -0
- data/lib/vagrant-vmware-esxi/plugin.rb +61 -0
- data/lib/vagrant-vmware-esxi/provider.rb +44 -0
- data/lib/vagrant-vmware-esxi/version.rb +6 -0
- data/locales/en.yml +65 -0
- data/vagrant-vmware-esxi.gemspec +27 -0
- metadata +151 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'net/ssh/simple'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ESXi
|
6
|
+
module Action
|
7
|
+
# This action will Destroy VM. unregister and delete the VM from disk.
|
8
|
+
class Destroy
|
9
|
+
def initialize(app, _env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::destroy')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
destroy(env)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def destroy(env)
|
20
|
+
@logger.info('vagrant-vmware-esxi, destroy: start...')
|
21
|
+
|
22
|
+
# Get config.
|
23
|
+
machine = env[:machine]
|
24
|
+
config = env[:machine].provider_config
|
25
|
+
|
26
|
+
@logger.info("vagrant-vmware-esxi, destroy: machine id: #{machine.id}")
|
27
|
+
@logger.info('vagrant-vmware-esxi, destroy: current state: '\
|
28
|
+
"#{env[:machine_state]}")
|
29
|
+
|
30
|
+
if env[:machine_state].to_s == 'not_created'
|
31
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.already_destroyed')
|
32
|
+
elsif env[:machine_state].to_s != 'powered_off'
|
33
|
+
raise Errors::ESXiError,
|
34
|
+
message: 'Guest VM should have been powered off...'
|
35
|
+
else
|
36
|
+
Net::SSH::Simple.sync(
|
37
|
+
user: config.esxi_username,
|
38
|
+
password: config.esxi_password,
|
39
|
+
port: config.esxi_hostport,
|
40
|
+
keys: config.esxi_private_keys
|
41
|
+
) do
|
42
|
+
|
43
|
+
r = ssh config.esxi_hostname,
|
44
|
+
"vim-cmd vmsvc/destroy #{machine.id}"
|
45
|
+
if r.exit_code != 0
|
46
|
+
raise Errors::ESXiError,
|
47
|
+
message => "Unable to destroy the VM:\n"\
|
48
|
+
" #{r.stdout}\n#{r.stderr}"
|
49
|
+
end
|
50
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
51
|
+
message: 'VM has been destroyed...')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'net/ssh/simple'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ESXi
|
6
|
+
module Action
|
7
|
+
# This action will halt (power off) the VM
|
8
|
+
class Halt
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::halt')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
halt(env)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def halt(env)
|
20
|
+
@logger.info('vagrant-vmware-esxi, halt: start...')
|
21
|
+
|
22
|
+
# Get config.
|
23
|
+
machine = env[:machine]
|
24
|
+
config = env[:machine].provider_config
|
25
|
+
|
26
|
+
if env[:machine_state].to_s == 'powered_off'
|
27
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.already_powered_off')
|
28
|
+
elsif env[:machine_state].to_s == 'not_created'
|
29
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.already_destroyed')
|
30
|
+
else
|
31
|
+
Net::SSH::Simple.sync(
|
32
|
+
user: config.esxi_username,
|
33
|
+
password: config.esxi_password,
|
34
|
+
port: config.esxi_hostport,
|
35
|
+
keys: config.esxi_private_keys
|
36
|
+
) do
|
37
|
+
|
38
|
+
r = ssh config.esxi_hostname,
|
39
|
+
"vim-cmd vmsvc/power.off #{machine.id}"
|
40
|
+
if r.exit_code != 0
|
41
|
+
raise Errors::ESXiError,
|
42
|
+
message: "Unable to power off the VM:\n"
|
43
|
+
" #{r.stdout}\n#{r.stderr}"
|
44
|
+
end
|
45
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.states.powered_off.short')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ESXi
|
5
|
+
module Action
|
6
|
+
# This action will get the SSH "availability".
|
7
|
+
class ReadSSHInfo
|
8
|
+
def initialize(app, _env)
|
9
|
+
@app = app
|
10
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::read_ssh_info')
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
env[:machine_ssh_info] = read_ssh_info(env)
|
15
|
+
@app.call(env)
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_ssh_info(env)
|
19
|
+
@logger.info('vagrant-vmware-esxi, read_ssh_info: start...')
|
20
|
+
|
21
|
+
# Get config.
|
22
|
+
machine = env[:machine]
|
23
|
+
config = env[:machine].provider_config
|
24
|
+
|
25
|
+
return :not_created if machine.id.nil?
|
26
|
+
|
27
|
+
@logger.info("vagrant-vmware-esxi, read_ssh_info: machine id: #{machine.id}")
|
28
|
+
@logger.info('vagrant-vmware-esxi, read_ssh_info: current state:'\
|
29
|
+
" #{env[:machine_state]}")
|
30
|
+
|
31
|
+
# Figure out vm_ipaddress
|
32
|
+
Net::SSH::Simple.sync(
|
33
|
+
user: config.esxi_username,
|
34
|
+
password: config.esxi_password,
|
35
|
+
port: config.esxi_hostport,
|
36
|
+
keys: config.esxi_private_keys
|
37
|
+
) do
|
38
|
+
|
39
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::'\
|
40
|
+
'read_ssh_info-net_ssh')
|
41
|
+
|
42
|
+
# ugly, but it works...
|
43
|
+
ssh_execute_cmd = "vim-cmd vmsvc/get.guest #{machine.id} |"
|
44
|
+
ssh_execute_cmd << 'grep -i "^ ipAddress"|'
|
45
|
+
ssh_execute_cmd << 'grep -oE "((1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])\.){3}(1?[0-9][0-9]?|2[0-4][0-9]|25[0-5])"'
|
46
|
+
r = ssh config.esxi_hostname, ssh_execute_cmd
|
47
|
+
|
48
|
+
ipaddress = r.stdout.strip
|
49
|
+
@logger.info('vagrant-vmware-esxi, read_ssh_info: ipaddress: '\
|
50
|
+
"#{ipaddress}")
|
51
|
+
|
52
|
+
return nil if (ipaddress == '') || (r.exit_code != 0)
|
53
|
+
|
54
|
+
return {
|
55
|
+
host: ipaddress,
|
56
|
+
port: 22
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ESXi
|
5
|
+
module Action
|
6
|
+
# This action reads the state of the machine and puts it in the
|
7
|
+
# `:machine_state_id` key in the environment.
|
8
|
+
class ReadState
|
9
|
+
def initialize(app, env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::read_state')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
env[:machine_state] = read_state(env)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_state(env)
|
20
|
+
@logger.info('vagrant-vmware-esxi, read_state: start...')
|
21
|
+
|
22
|
+
# Get config.
|
23
|
+
machine = env[:machine]
|
24
|
+
config = env[:machine].provider_config
|
25
|
+
|
26
|
+
return :not_created if machine.id.to_i < 1
|
27
|
+
|
28
|
+
@logger.info("vagrant-vmware-esxi, read_state: machine id: #{machine.id}")
|
29
|
+
@logger.info("vagrant-vmware-esxi, read_state: current state: #{env[:machine_state]}")
|
30
|
+
|
31
|
+
Net::SSH::Simple.sync(
|
32
|
+
user: config.esxi_username,
|
33
|
+
password: config.esxi_password,
|
34
|
+
port: config.esxi_hostport,
|
35
|
+
keys: config.esxi_private_keys
|
36
|
+
) do
|
37
|
+
|
38
|
+
r = ssh config.esxi_hostname,
|
39
|
+
"vim-cmd vmsvc/getallvms|grep -q \"^#{machine.id} \" && "\
|
40
|
+
"vim-cmd vmsvc/power.getstate #{machine.id} || return 254"
|
41
|
+
power_status = r.stdout
|
42
|
+
|
43
|
+
return :not_created if r.exit_code == 254
|
44
|
+
if power_status == "" or r.exit_code != 0
|
45
|
+
raise Errors::ESXiError,
|
46
|
+
message: 'Unable to get VM Power State!'
|
47
|
+
end
|
48
|
+
|
49
|
+
if (power_status.include? "Powered on") && !env[:machine].ssh_info.nil?
|
50
|
+
return :running
|
51
|
+
elsif power_status.include? "Powered on"
|
52
|
+
return :powered_on
|
53
|
+
elsif power_status.include? "Powered off"
|
54
|
+
return :powered_off
|
55
|
+
elsif power_status.include? "Suspended"
|
56
|
+
return :suspended
|
57
|
+
end
|
58
|
+
|
59
|
+
return nil
|
60
|
+
end
|
61
|
+
|
62
|
+
return :not_created
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'net/ssh/simple'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ESXi
|
6
|
+
module Action
|
7
|
+
# This action will Resume (power on) the VM
|
8
|
+
class Resume
|
9
|
+
def initialize(app, _env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::resume')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
resume(env)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def resume(env)
|
20
|
+
@logger.info('vagrant-vmware-esxi, resume: start...')
|
21
|
+
|
22
|
+
# Get config.
|
23
|
+
machine = env[:machine]
|
24
|
+
config = env[:machine].provider_config
|
25
|
+
|
26
|
+
@logger.info("vagrant-vmware-esxi, resume: machine id: #{machine.id}")
|
27
|
+
@logger.info("vagrant-vmware-esxi, resume: current state: #{env[:machine_state]}")
|
28
|
+
|
29
|
+
if (env[:machine_state].to_s == 'powered_on') ||
|
30
|
+
(env[:machine_state].to_s == 'running')
|
31
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.already_powered_on')
|
32
|
+
elsif env[:machine_state].to_s == 'not_created'
|
33
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
34
|
+
message: 'Cannot resume in this state')
|
35
|
+
elsif (env[:machine_state].to_s == 'powered_off') ||
|
36
|
+
(env[:machine_state].to_s == 'suspended')
|
37
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
38
|
+
message: 'Attempting to resume')
|
39
|
+
|
40
|
+
Net::SSH::Simple.sync(
|
41
|
+
user: config.esxi_username,
|
42
|
+
password: config.esxi_password,
|
43
|
+
port: config.esxi_hostport,
|
44
|
+
keys: config.esxi_private_keys
|
45
|
+
) do
|
46
|
+
|
47
|
+
r = ssh config.esxi_hostname, "vim-cmd vmsvc/power.on #{machine.id}"
|
48
|
+
if r.exit_code != 0
|
49
|
+
raise Errors::ESXiError,
|
50
|
+
message: "Unable to resume the VM:\n"\
|
51
|
+
" #{r.stdout}\n#{r.stderr}"
|
52
|
+
end
|
53
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
54
|
+
message: 'VM has been resumed...')
|
55
|
+
end
|
56
|
+
else
|
57
|
+
raise Errors::ESXiError, message: 'Unknown state to resume...'
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'net/ssh/simple'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ESXi
|
6
|
+
module Action
|
7
|
+
# This action will Suspend the VM
|
8
|
+
class Suspend
|
9
|
+
def initialize(app, _env)
|
10
|
+
@app = app
|
11
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::suspend')
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
suspend(env)
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
|
19
|
+
def suspend(env)
|
20
|
+
@logger.info('vagrant-vmware-esxi, suspend: start...')
|
21
|
+
|
22
|
+
# Get config.
|
23
|
+
machine = env[:machine]
|
24
|
+
config = env[:machine].provider_config
|
25
|
+
|
26
|
+
@logger.info("vagrant-vmware-esxi, suspend: machine id: #{machine.id}")
|
27
|
+
@logger.info("vagrant-vmware-esxi, suspend: current state: #{env[:machine_state]}")
|
28
|
+
|
29
|
+
if env[:machine_state].to_s == 'suspended'
|
30
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.already_suspended')
|
31
|
+
elsif (env[:machine_state].to_s == 'powered_off') ||
|
32
|
+
(env[:machine_state].to_s == 'not_created')
|
33
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
34
|
+
message: 'Cannot suspend in this state')
|
35
|
+
else
|
36
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
37
|
+
message: 'Attempting to suspend')
|
38
|
+
|
39
|
+
Net::SSH::Simple.sync(
|
40
|
+
user: config.esxi_username,
|
41
|
+
password: config.esxi_password,
|
42
|
+
port: config.esxi_hostport,
|
43
|
+
keys: config.esxi_private_keys,
|
44
|
+
timeout: 300
|
45
|
+
) do
|
46
|
+
|
47
|
+
r = ssh config.esxi_hostname, "vim-cmd vmsvc/power.suspend #{machine.id}"
|
48
|
+
if r.exit_code != 0
|
49
|
+
raise Errors::ESXiError,
|
50
|
+
message: "Unable to suspend the VM:\n"\
|
51
|
+
" #{r.stdout}\n#{r.stderr}"
|
52
|
+
end
|
53
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.support')
|
54
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.states.suspended.short')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'log4r'
|
2
|
+
require 'timeout'
|
3
|
+
|
4
|
+
module VagrantPlugins
|
5
|
+
module ESXi
|
6
|
+
module Action
|
7
|
+
# This action will wait for a machine to reach a specific state or quit
|
8
|
+
# by timeout
|
9
|
+
class WaitForState
|
10
|
+
# env[:result] will be false in case of timeout.
|
11
|
+
# @param [Symbol] state Target machine state.
|
12
|
+
# @param [Number] timeout Timeout in seconds.
|
13
|
+
def initialize(app, _env, state, timeout)
|
14
|
+
@app = app
|
15
|
+
@logger = Log4r::Logger.new('vagrant_vmware_esxi::action::wait_for_state')
|
16
|
+
@state = state
|
17
|
+
@timeout = timeout
|
18
|
+
end
|
19
|
+
|
20
|
+
def call(env)
|
21
|
+
env[:result] = 'True'
|
22
|
+
if env[:machine].state.id != @state
|
23
|
+
env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
|
24
|
+
message: "Waiting for state \"#{@state}\"")
|
25
|
+
begin
|
26
|
+
Timeout.timeout(@timeout) do
|
27
|
+
until env[:machine].state.id == @state
|
28
|
+
sleep 4
|
29
|
+
end
|
30
|
+
end
|
31
|
+
rescue Timeout::Error
|
32
|
+
env[:result] = 'False' # couldn't reach state in time
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@app.call(env)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# Config
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module ESXi
|
5
|
+
# Config class
|
6
|
+
class Config < Vagrant.plugin('2', :config)
|
7
|
+
attr_accessor :esxi_hostname
|
8
|
+
attr_accessor :esxi_hostport
|
9
|
+
attr_accessor :esxi_username
|
10
|
+
attr_accessor :esxi_password
|
11
|
+
attr_accessor :esxi_private_keys
|
12
|
+
attr_accessor :ssh_username
|
13
|
+
attr_accessor :private_key_path
|
14
|
+
attr_accessor :vmname
|
15
|
+
attr_accessor :vmname_prefix
|
16
|
+
attr_accessor :vm_disk_store
|
17
|
+
attr_accessor :virtual_network
|
18
|
+
attr_accessor :resource_pool
|
19
|
+
attr_accessor :memsize
|
20
|
+
attr_accessor :numvcpus
|
21
|
+
attr_accessor :custom_vmx_settings
|
22
|
+
attr_accessor :allow_overwrite
|
23
|
+
attr_accessor :system_private_keys_path
|
24
|
+
def initialize
|
25
|
+
@esxi_hostname = nil
|
26
|
+
@esxi_hostport = 22
|
27
|
+
@esxi_username = 'root'
|
28
|
+
@esxi_password = nil
|
29
|
+
@esxi_private_keys = UNSET_VALUE
|
30
|
+
@ssh_username = 'vagrant'
|
31
|
+
@private_key_path = UNSET_VALUE
|
32
|
+
@vmname = nil
|
33
|
+
@vmname_prefix = 'V-'
|
34
|
+
@vm_disk_store = nil
|
35
|
+
@virtual_network = nil
|
36
|
+
@resource_pool = nil
|
37
|
+
@memsize = UNSET_VALUE
|
38
|
+
@numvcpus = UNSET_VALUE
|
39
|
+
@custom_vmx_settings = UNSET_VALUE
|
40
|
+
@allow_overwrite = 'False'
|
41
|
+
@system_private_keys_path = [
|
42
|
+
'~/.ssh/id_rsa',
|
43
|
+
'~/.ssh/id_ecdsa',
|
44
|
+
'~/.ssh/id_ed25519',
|
45
|
+
'~/.ssh/id_dsa'
|
46
|
+
]
|
47
|
+
end
|
48
|
+
|
49
|
+
def finalize!
|
50
|
+
@private_key_path = nil if @private_key_path == UNSET_VALUE
|
51
|
+
@ssh_username = nil if @ssh_username == UNSET_VALUE
|
52
|
+
@esxi_private_keys = @system_private_keys_path if @esxi_private_keys == UNSET_VALUE
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|