vagrant-vmware-esxi 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,175 @@
1
+ vagrant-vmware-esxi plugin
2
+ ==========================
3
+ This is a Vagrant plugin that adds a VMware ESXi provider support. This allows Vagrant to control and provision VMs directly on an ESXi hypervisor without a need for vCenter or VShpere. ESXi hypervisor is a free download from VMware!
4
+ >https://www.vmware.com/go/get-free-esxi
5
+
6
+
7
+ Features
8
+ --------
9
+ * Any of the vmware Box formats should be compatible.
10
+ * vmware_destop, vmware_fusion, vmware_workstation...
11
+ * Will automatically download boxes from the web.
12
+ * Will automatically upload the box to your ESXi host.
13
+ * Automatic or manual VM names.
14
+ * Automatic VM names are "PREFIX-HOSTNAME-USERNAME-DIR".
15
+ * Multi machine capable.
16
+ * Supports adding your VM to a Resource Pools to partition CPU and memory usage from other VMs on your ESXi host.
17
+ * suspend / resume
18
+ * rsync, using built-in Vagrant synced folders.
19
+ * Provision using built-in Vagrant provisioner.
20
+
21
+ Requirements
22
+ ------------
23
+ 1. This plugin requires ovftool from VMware. Download from VMware website.
24
+ >https://www.vmware.com/support/developer/ovf/
25
+ 1. You MUST enable ssh access on your ESXi hypervisor.
26
+ * Google 'How to enable ssh access on esxi'
27
+ 1. The boxes should have open-vm-tools or vmware-tools installed.
28
+
29
+ Why this plugin?
30
+ ----------------
31
+ Not everyone has vCenter / vSphere... vCenter cost $$$. ESXi is free!
32
+
33
+ How to install
34
+ --------------
35
+ ```
36
+ vagrant plugin install vagrant-vmware-esxi
37
+ ```
38
+ How to configure
39
+ ----------------
40
+
41
+ 1. cd SOMEDIR
42
+ 1. `vagrant init`
43
+ 1. `vi Vagrantfile` # setup access your ESXi host and to set some preferences.
44
+ ```ruby
45
+ Vagrant.configure("2") do |config|
46
+
47
+ # Box, Select any box created for VMware that is compatible with
48
+ # the ovftool. To get maximum compatiblity You should download
49
+ # and install the latest version for your OS.
50
+ # https://www.vmware.com/support/developer/ovf/
51
+ #
52
+ # If your box is stuck at "Powered On", then most likely
53
+ # the system didn't have the vmware tools installed.
54
+ #
55
+ # Here are some of the MANY examples....
56
+ config.vm.box = 'hashicorp/precise64'
57
+ #config.vm.box = 'steveant/CentOS-7.0-1406-Minimal-x64'
58
+ #config.vm.box = 'geerlingguy/ubuntu1604'
59
+ #config.vm.box = 'laravel/homestead'
60
+ #config.vm.box = 'centos/7'
61
+ #config.vm.box = 'bento/ubuntu-14.04'
62
+
63
+ # Currently this tool supports rsync ONLY. NFS is not working yet
64
+ config.vm.synced_folder('.', '/Vagrantfiles', type: 'rsync')
65
+
66
+ #
67
+ # Provider (esxi) settings
68
+ #
69
+ config.vm.provider :esxi do |esxi|
70
+
71
+ # REQUIRED! ESXi hostname/IP
72
+ # You MUST specify a esxi_hostname or IP, uless you
73
+ # were lucky enough to name your esxi host "esxi". :-)
74
+ esxi.esxi_hostname = "esxi"
75
+
76
+ # ESXi username
77
+ # Default is "root".
78
+ esxi.esxi_username = "root"
79
+
80
+ #
81
+ # A NOTE about esxi_password / ssh keys!!
82
+ #
83
+ # If you don't specify a password and do not use ssh
84
+ # keys, you wil; be entering your esxi password A LOT!
85
+ #
86
+ # From your command line, you should be able to run
87
+ # following command without erros and be able to get to
88
+ # the esxi command prompt.
89
+ #
90
+ # $ ssh root@ESXi_IP_ADDRESS
91
+
92
+ # IMPORTANT! ESXi password.
93
+ # The ssh connections to esxi will try your ssh
94
+ # keys first. However the ovftool does NOT! To make
95
+ # vagrant up fully password-less, you will need to
96
+ # enter your password here....
97
+ esxi.esxi_password = nil
98
+
99
+ # ESXi ssh keys
100
+ # The Default is to use system defaults, However
101
+ # you can specify an array of keys here...
102
+ #esxi.esxi_private_keys = []
103
+
104
+ # SSH port.
105
+ # Default port 22
106
+ #esxi.esxi_hostport = 22
107
+
108
+ # REQUIRED! Virtual Network
109
+ # You MUST specify a Virtual Network!
110
+ # The default is fail if no Virtual Network is set!
111
+ esxi.virtual_network = "vmnet_example"
112
+
113
+ # OPTIONAL. Specify a Disk Store
114
+ # Default is to use the least used Disk Store.
115
+ #esxi.vm_disk_store = "DS_001"
116
+
117
+ # OPTIONAL. Guest VM name to be created/used.
118
+ # The Default will be automatically generated
119
+ # and will be based on the vmname_prefix,
120
+ # hostname, username, path...
121
+ #esxi.vmname = "Custome_Guest_VM_Name"
122
+
123
+ # OPTIONAL. When automatically naming VMs, use
124
+ # this prifix.
125
+ #esxi.vmname_prefix = "V-"
126
+
127
+ # OPTIONAL. Memory size override
128
+ # The default is to use the memory size specified in the
129
+ # vmx file, however you can specify a new value here.
130
+ #esxi.memsize = "2048"
131
+
132
+ # OPTIONAL. Virtual CPUs override
133
+ # The default is to use the number of virt cpus specified
134
+ # in the vmx file, however you can specify a new value here.
135
+ #esxi.numvcpus = "2"
136
+
137
+ # OPTIONAL. Resource Pool
138
+ # The default is to create VMs in the "root". You can
139
+ # specify a resource pool here to partition memory and
140
+ # cpu usage away from other systems on your esxi host.
141
+ # The resource pool must already exist and be configured.
142
+ # Vagrant will NOT create it for you.
143
+ #esxi.resource_pool = "/Vagrant"
144
+
145
+ # DANGEROUS! Allow Overwrite
146
+ # Set this to 'True' will overwrite existing VMs (with the same name)
147
+ # when you run vagrant up. ie, if the vmname already exists,
148
+ # it will be destroyed, then over written... This is helpful
149
+ # if you have a VM that vagrant lost control (lost association).
150
+ #esxi.allow_overwrite = 'True'
151
+
152
+ end
153
+ end
154
+ ```
155
+
156
+ Basic usage
157
+ -----------
158
+ 1. `vagrant up --provider=esxi`
159
+ 1. To access the VM, use `vagrant ssh`
160
+ 1. To destroy the VM, use `vagrant destroy`
161
+ 1. Some other fun stuff you can do.
162
+ * `vagrant status`
163
+ * `vagrant suspend`
164
+ * `vagrant resume`
165
+ * `vagrant halt`
166
+ * `vagrant provision`
167
+
168
+
169
+ Known issues
170
+ ------------
171
+ * NFS using built-in Vagrant synced folders is not yet supported.
172
+ * Multi machines may not provision one VM if the boxes are different.
173
+ * I found this seems to be a problem with libvirt also, so I'm assuming it's a vagrant problem...
174
+ * Cleanup doesn't always destroy a VM that has been partially built. Use the allow_overwrite = 'True' option if you need to force a rebuild.
175
+ * ovftool for windows doesn't put ovftool.exe in your path. You can manually set your path, or install ovftool in the \HashiCorp\Vagrant\bin directory.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ require "rubygems"
2
+ require "bundler/gem_tasks"
3
+ require "net/ssh/simple"
4
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,4 @@
1
+
2
+ {
3
+ "provider": "vmware-esxi"
4
+ }
@@ -0,0 +1,18 @@
1
+ require 'pathname'
2
+ require 'vagrant-vmware-esxi/plugin'
3
+
4
+ module VagrantPlugins
5
+ # Main entry for ESXi vagrant plugin
6
+ module ESXi
7
+ lib_path = Pathname.new(File.expand_path('../vagrant-vmware-esxi', __FILE__))
8
+ autoload :Action, lib_path.join('action')
9
+ autoload :Errors, lib_path.join('errors')
10
+
11
+ # This returns the path to the source of this plugin.
12
+ #
13
+ # @return [Pathname]
14
+ def self.source_root
15
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,119 @@
1
+ require 'vagrant/action/builder'
2
+
3
+ module VagrantPlugins
4
+ module ESXi
5
+ # actions and how to run them
6
+ module Action
7
+ include Vagrant::Action::Builtin
8
+ def self.action_connect_esxi
9
+ Vagrant::Action::Builder.new.tap do |b|
10
+ b.use ConnectESXi
11
+ end
12
+ end
13
+
14
+ def self.action_halt
15
+ Vagrant::Action::Builder.new.tap do |b|
16
+ b.use ReadState
17
+ b.use Halt
18
+ end
19
+ end
20
+
21
+ def self.action_suspend
22
+ Vagrant::Action::Builder.new.tap do |b|
23
+ b.use ReadState
24
+ b.use Suspend
25
+ end
26
+ end
27
+
28
+ def self.action_resume
29
+ Vagrant::Action::Builder.new.tap do |b|
30
+ b.use ReadState
31
+ b.use Resume
32
+ end
33
+ end
34
+
35
+ def self.action_destroy
36
+ Vagrant::Action::Builder.new.tap do |b|
37
+ b.use action_halt
38
+ b.use ReadState
39
+ b.use Destroy
40
+ end
41
+ end
42
+
43
+ def self.action_up
44
+ Vagrant::Action::Builder.new.tap do |b|
45
+ b.use ConfigValidate
46
+ b.use ConnectESXi
47
+ b.use HandleBox
48
+ b.use ReadState
49
+ b.use CreateVM
50
+ b.use ReadState
51
+ b.use Boot
52
+ b.use Call, WaitForState, :running, 240 do |env1, b1|
53
+ if env1[:result] == 'True'
54
+ b1.use action_provision
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ def self.action_reload
61
+ Vagrant::Action::Builder.new.tap do |b|
62
+ b.use Call, ReadState do |env1, b1|
63
+ if env1[:machine_state].to_s == 'powered_on'
64
+ b1.use action_halt
65
+ end
66
+ b1.use action_up
67
+ end
68
+ end
69
+ end
70
+
71
+ def self.action_read_state
72
+ Vagrant::Action::Builder.new.tap do |b|
73
+ b.use ReadSSHInfo
74
+ b.use ReadState
75
+ end
76
+ end
77
+
78
+ def self.action_read_ssh_info
79
+ Vagrant::Action::Builder.new.tap do |b|
80
+ b.use ReadSSHInfo
81
+ end
82
+ end
83
+
84
+ def self.action_ssh
85
+ Vagrant::Action::Builder.new.tap do |b|
86
+ b.use ReadState
87
+ b.use ReadSSHInfo
88
+ b.use SSHExec
89
+ b.use SSHRun
90
+ end
91
+ end
92
+
93
+ def self.action_provision
94
+ Vagrant::Action::Builder.new.tap do |b|
95
+ b.use Call, WaitForState, :running, 240 do |env1, b1|
96
+ if env1[:result] == 'True'
97
+ b1.use ReadState
98
+ b1.use Provision
99
+ b1.use SyncedFolderCleanup
100
+ b1.use SyncedFolders
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ action_root = Pathname.new(File.expand_path('../action', __FILE__))
107
+ autoload :ConnectESXi, action_root.join('connect_esxi')
108
+ autoload :CreateVM, action_root.join('createvm')
109
+ autoload :ReadState, action_root.join('read_state')
110
+ autoload :ReadSSHInfo, action_root.join('read_ssh_info')
111
+ autoload :Boot, action_root.join('boot')
112
+ autoload :Halt, action_root.join('halt')
113
+ autoload :Destroy, action_root.join('destroy')
114
+ autoload :Suspend, action_root.join('suspend')
115
+ autoload :Resume, action_root.join('resume')
116
+ autoload :WaitForState, action_root.join('wait_for_state')
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,59 @@
1
+ require 'log4r'
2
+ require 'net/ssh/simple'
3
+
4
+ module VagrantPlugins
5
+ module ESXi
6
+ module Action
7
+ # This action Boots (power on) the VM
8
+ class Boot
9
+ def initialize(app, _env)
10
+ @app = app
11
+ @logger = Log4r::Logger.new('vagrant_vmware_esxi::action::boot')
12
+ end
13
+
14
+ def call(env)
15
+ boot(env)
16
+ @app.call(env)
17
+ end
18
+
19
+ def boot(env)
20
+ @logger.info('vagrant-vmware-esxi, boot: start...')
21
+
22
+ # Get config.
23
+ machine = env[:machine]
24
+ config = env[:machine].provider_config
25
+
26
+ @logger.info("vagrant-vmware-esxi, boot: machine id: #{machine.id}")
27
+ @logger.info('vagrant-vmware-esxi, boot: current state: '\
28
+ "#{env[:machine_state]}")
29
+
30
+ if env[:machine_state].to_s == 'powered_on' ||
31
+ env[:machine_state].to_s == 'running'
32
+ env[:ui].info I18n.t('vagrant_vmware_esxi.already_powered_on')
33
+ elsif env[:machine_state].to_s == 'not_created'
34
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
35
+ message: 'Cannot boot in this state')
36
+ else
37
+ Net::SSH::Simple.sync(
38
+ user: config.esxi_username,
39
+ password: config.esxi_password,
40
+ port: config.esxi_hostport,
41
+ keys: config.esxi_private_keys
42
+ ) do
43
+
44
+ r = ssh config.esxi_hostname,
45
+ "vim-cmd vmsvc/power.on #{machine.id}"
46
+ if r.exit_code != 0
47
+ raise Errors::ESXiError,
48
+ message: "Unable to power on VM:\n"\
49
+ " #{r.stdout}\n#{r.stderr}"
50
+ end
51
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
52
+ message: 'VM has been Powered On...')
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -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 connects to the ESXi, verifies credentials and
8
+ # validates if it's a ESXi host
9
+ class ConnectESXi
10
+ def initialize(app, _env)
11
+ @app = app
12
+ @logger = Log4r::Logger.new('vagrant_vmware_esxi::action::connect_esxi')
13
+ end
14
+
15
+ def call(env)
16
+ connect_esxi(env)
17
+ @app.call(env)
18
+ end
19
+
20
+ def connect_esxi(env)
21
+ @logger.info('vagrant-vmware-esxi, connect_esxi: start...')
22
+
23
+ # Get config.
24
+ config = env[:machine].provider_config
25
+
26
+ if config.esxi_private_keys.is_a? Array
27
+ config.esxi_private_keys = [
28
+ '~/.ssh/id_rsa',
29
+ '~/.ssh/id_dsa',
30
+ '~/.ssh/id_ecdsa',
31
+ '~/.ssh/id_ed25519'
32
+ ]
33
+ end
34
+ @logger.info('vagrant-vmware-esxi, connect_esxi: esxi_private_keys: '\
35
+ "#{config.esxi_private_keys}")
36
+
37
+ Net::SSH::Simple.sync(
38
+ user: config.esxi_username,
39
+ password: config.esxi_password,
40
+ port: config.esxi_hostport,
41
+ keys: config.esxi_private_keys
42
+ ) do
43
+
44
+ r = ssh config.esxi_hostname,
45
+ 'esxcli system version get | grep Version:'
46
+ if (!r.stdout.include? 'Version:') || (r.exit_code != 0)
47
+ raise Errors::ESXiConfigError,
48
+ message: "Unable to access ESXi host.\n"\
49
+ 'Verify esxi_hostname, esxi_hostport, '\
50
+ 'esxi_username, esxi_password in your Vagrantfile.'
51
+ end
52
+ end
53
+ @logger.info('vagrant-vmware-esxi, connect_esxi: connect success...')
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,302 @@
1
+ require 'log4r'
2
+ require 'net/ssh/simple'
3
+
4
+ module VagrantPlugins
5
+ module ESXi
6
+ module Action
7
+ # This action connects to the ESXi, verifies credentials and
8
+ # validates if it's a ESXi host
9
+ class CreateVM
10
+ def initialize(app, _env)
11
+ @app = app
12
+ @logger = Log4r::Logger.new('vagrant_vmware_esxi::action::createvm')
13
+ end
14
+
15
+ def call(env)
16
+ createvm(env)
17
+ @app.call(env)
18
+ end
19
+
20
+ def createvm(env)
21
+ @logger.info('vagrant-vmware-esxi, createvm: start...')
22
+
23
+ # Get config.
24
+ machine = env[:machine]
25
+ config = env[:machine].provider_config
26
+
27
+ if env[:machine_state].to_s == 'not_created'
28
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vmbuild_not_done')
29
+ else
30
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vmbuild_already_done')
31
+ return
32
+ end
33
+
34
+ # Set guestvm_vmname
35
+ if !env[:machine].config.vm.hostname.nil?
36
+ # A hostname has been set, so use it. (multi node)
37
+ guestvm_vmname = env[:machine].config.vm.hostname
38
+ elsif config.vmname.nil?
39
+ # Nothing set, so generate our own
40
+ guestvm_vmname = config.vmname_prefix
41
+ guestvm_vmname << `hostname`.strip
42
+ guestvm_vmname << '-'
43
+ guestvm_vmname << `whoami`.gsub!(/[^0-9A-Za-z]/, '').strip
44
+ guestvm_vmname << '-'
45
+ base = File.basename machine.env.cwd.to_s
46
+ guestvm_vmname << base
47
+ config.vmname = guestvm_vmname
48
+ else
49
+ # A vmname has been set, so use it.
50
+ guestvm_vmname = config.vmname
51
+ end
52
+ @logger.info("vagrant-vmware-esxi, createvm: config.vmname: #{config.vmname}")
53
+
54
+ #
55
+ # Source vmx / vmdk files
56
+ src_dir = env[:machine].box.directory
57
+ @logger.info("vagrant-vmware-esxi, createvm: src_dir: #{src_dir}")
58
+
59
+ vmx_file = Dir.glob("#{src_dir}/*.vmx").first
60
+ vmdk_files = Dir.glob("#{src_dir}/*.vmdk")
61
+ @logger.info("vagrant-vmware-esxi, createvm: vmx_file: #{vmx_file}")
62
+ @logger.info("vagrant-vmware-esxi, createvm: vmdk_files: #{vmdk_files}")
63
+
64
+ #
65
+ # Open the network connection
66
+ #
67
+ Net::SSH::Simple.sync(
68
+ user: config.esxi_username,
69
+ password: config.esxi_password,
70
+ port: config.esxi_hostport,
71
+ keys: config.esxi_private_keys
72
+ ) do
73
+
74
+ @logger = Log4r::Logger.new('vagrant_vmware_esxi::action::createvm-ssh')
75
+
76
+ #
77
+ # Figure out DataStore
78
+ r = ssh config.esxi_hostname,
79
+ 'esxcli storage filesystem list | '\
80
+ 'grep "/vmfs/volumes/.*true VMFS" | sort -nk7'
81
+
82
+ availvolumes = r.stdout.dup
83
+ if (r == '') || (r.exit_code != 0)
84
+ raise Errors::ESXiError,
85
+ message: 'Unable to get list of Disk Stores:'
86
+ end
87
+
88
+ # Use least-used if vm_disk_store is not set (or not found)
89
+ if config.vm_disk_store.nil?
90
+ desired_ds = '--- Least Used ---'
91
+ else
92
+ desired_ds = config.vm_disk_store.to_s
93
+ end
94
+
95
+ for line in availvolumes.each_line do
96
+ if line =~ %r{ #{desired_ds} }
97
+ guestvm_ds = line.split(' ')[0].to_s
98
+ guestvm_dsname = line.split(' ')[1]
99
+ break
100
+ end
101
+ guestvm_ds = line.split(' ')[0].to_s
102
+ guestvm_dsname = line.split(' ')[1]
103
+ end
104
+
105
+ if (guestvm_dsname != desired_ds) &&
106
+ !config.vm_disk_store.nil?
107
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
108
+ message: 'WARNING : '\
109
+ "#{config.vm_disk_store} not "\
110
+ "found, using #{guestvm_dsname}.")
111
+ end
112
+
113
+ dst_dir = "#{guestvm_ds}/#{guestvm_vmname}"
114
+ @logger.info("vagrant-vmware-esxi, createvm: dst_dir: #{dst_dir}")
115
+ @logger.info('vagrant-vmware-esxi, createvm: '\
116
+ "guestvm_dsname: #{guestvm_dsname}")
117
+
118
+ #
119
+ # Figure out network
120
+ #
121
+ r = ssh config.esxi_hostname,
122
+ 'esxcli network vswitch standard list |'\
123
+ 'grep Portgroups | sed "s/^ Portgroups: //g" |'\
124
+ 'sed "s/,.*$//g"'
125
+ availnetworks = r.stdout.dup
126
+ if (availnetworks == '') || (r.exit_code != 0)
127
+ raise Errors::ESXiError,
128
+ message: "Unable to get list of Virtual Networks:\n"\
129
+ "#{r.stderr}"
130
+ end
131
+
132
+ guestvm_network = nil
133
+ availnetworkslist = availnetworks.dup
134
+ for line in availnetworks.each_line do
135
+ if line =~ %r{#{config.virtual_network}}
136
+ guestvm_network = config.virtual_network
137
+ end
138
+ end
139
+
140
+ if guestvm_network.nil?
141
+ raise Errors::ESXiConfigError,
142
+ message: "You MUST specify a valid virtual network.\n"\
143
+ "virtual_network (#{config.virtual_network}).\n"\
144
+ "Available Virtual Networks:\n#{availnetworkslist}"
145
+ end
146
+ @logger.info('vagrant-vmware-esxi, createvm: '\
147
+ "virtual_network: #{guestvm_network}")
148
+
149
+ # finalize some paramaters
150
+ if (config.memsize.is_a? String) || (config.memsize.is_a? Integer)
151
+ desired_memsize = config.memsize.to_s.to_i
152
+ end
153
+ if (config.numvcpus.is_a? String) || (config.numvcpus.is_a? Integer)
154
+ desired_numvcpus = config.numvcpus.to_s.to_i
155
+ end
156
+
157
+ #
158
+ # Fix/clean up vmx file.
159
+ #
160
+ new_vmx_contents = ''
161
+ File.readlines(vmx_file).each do |line|
162
+
163
+ if line.match(/^displayname =/i)
164
+ new_vmx_contents << "displayname = \"#{guestvm_vmname}\"\n"
165
+ elsif line.match(/^memsize =/i) && (!desired_memsize.nil?)
166
+ new_vmx_contents << "memsize = \"#{desired_memsize}\"\n"
167
+ elsif line.match(/^numvcpus =/i) && (!desired_numvcpus.nil?)
168
+ new_vmx_contents << "numvcpus = \"#{desired_numvcpus}\"\n"
169
+ elsif line.match(/^ethernet0.networkName =/i)
170
+ new_vmx_contents << "ethernet0.networkName = \"#{guestvm_network}\"\n"
171
+ elsif line.match(/^ethernet0.addressType =.*static/i)
172
+ new_vmx_contents << 'ethernet0.addressType = \"generated\"'
173
+ elsif line.match(/^ethernet[1-9]/i) ||
174
+ line.match(/^ethernet0.address = /i) ||
175
+ line.match(/^ethernet0.generatedAddress = /i) ||
176
+ line.match(/^ethernet0.generatedAddressOffset = /i)
177
+ # Do nothing, delete these lines
178
+ else
179
+ new_vmx_contents << line
180
+ end
181
+ end
182
+
183
+ # finalize vmx.
184
+ unless new_vmx_contents =~ %r{^numvcpus =}i
185
+ if desired_numvcpus.nil?
186
+ new_vmx_contents << "numvcpus = \"1\"\n"
187
+ else
188
+ new_vmx_contents << "numvcpus = \"#{desired_numvcpus}\"\n"
189
+ end
190
+ end
191
+
192
+ unless new_vmx_contents =~ %r{^ethernet0.networkName =}i
193
+ new_vmx_contents << "ethernet0.networkName = \"#{guestvm_network}\"\n"
194
+ end
195
+
196
+ if config.custom_vmx_settings.is_a? Array
197
+ env[:machine].provider_config.custom_vmx_settings.each do |k, v|
198
+ new_vmx_contents << "#{k} = \"#{v}\"\n"
199
+ end
200
+ end
201
+
202
+ # Write new vmx file
203
+ filename_only = File.basename vmx_file, '.vmx'
204
+ path_only = File.dirname vmx_file
205
+ new_vmx_file = "#{path_only}/ZZZZ_#{guestvm_vmname}.vmx"
206
+
207
+ File.open(new_vmx_file, 'w') { |file|
208
+ file.write(new_vmx_contents)
209
+ file.close
210
+ }
211
+
212
+ #
213
+ # Check if using a Resource Pool
214
+ if config.resource_pool.is_a? String
215
+ if config.resource_pool =~ %r{^\/}
216
+ resource_pool = config.resource_pool
217
+ else
218
+ resource_pool = '/'
219
+ resource_pool << config.resource_pool
220
+ end
221
+ else
222
+ resource_pool = ''
223
+ end
224
+
225
+ if (config.allow_overwrite =~ %r{true}i) ||
226
+ (config.allow_overwrite =~ %r{yes}i)
227
+ overwrite_opts = '--overwrite --powerOffTarget'
228
+ else
229
+ overwrite_opts = nil
230
+ end
231
+
232
+ #
233
+ # Display build summary
234
+ numvcpus = new_vmx_contents.match(/^numvcpus =.*/i)
235
+ .to_s.gsub(/^numvcpus =/i, '').gsub(/\"/, '')
236
+ memsize = new_vmx_contents.match(/^memsize =.*/i)
237
+ .to_s.gsub(/^memsize =/i, '').gsub(/\"/, '')
238
+ guestOS = new_vmx_contents.match(/^guestOS =.*/i)
239
+ .to_s.gsub(/^guestOS =/i, '').gsub(/\"/, '')
240
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
241
+ message: "ESXi host : #{config.esxi_hostname}")
242
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
243
+ message: "VM Name : #{guestvm_vmname}")
244
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
245
+ message: "CPUS :#{numvcpus}")
246
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
247
+ message: "Memsize (MB) :#{memsize}")
248
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
249
+ message: "Guest OS type :#{guestOS}")
250
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
251
+ message: "Disk Store : #{guestvm_dsname}")
252
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
253
+ message: "NetworkName : \"#{guestvm_network}\"")
254
+ unless overwrite_opts.nil?
255
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
256
+ message: 'Allow Overwrite : True')
257
+ end
258
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
259
+ message: "Resource Pool : #{resource_pool}")
260
+ #
261
+ # Using ovftool, import vmx in box folder, export to ESXi server
262
+ #
263
+ unless system 'ovftool --version'
264
+ raise Errors::ESXiConfigError,
265
+ message: 'ovftool not found or not in your path.'\
266
+ " Please download and "\
267
+ ' install from http://www.vmware.com.'
268
+ end
269
+ ovf_cmd = "ovftool --noSSLVerify #{overwrite_opts} "\
270
+ "-nw=\"#{guestvm_network}\" -dm=thin --powerOn "\
271
+ "-ds=\"#{guestvm_dsname}\" --name=\"#{guestvm_vmname}\" "\
272
+ "\"#{new_vmx_file}\" vi://#{config.esxi_username}:"\
273
+ "#{config.esxi_password}@#{config.esxi_hostname}"\
274
+ "#{resource_pool}"
275
+
276
+ # Security bug if unremarked! Password will be exposed in log file.
277
+ # @logger.info("vagrant-vmware-esxi, createvm: ovf_cmd #{ovf_cmd}")
278
+ unless system "#{ovf_cmd}"
279
+ raise Errors::ESXiConfigError, message: 'Error with ovftool...'
280
+ end
281
+
282
+ # VMX file is not needed any longer
283
+ File.delete(new_vmx_file)
284
+
285
+ r = ssh config.esxi_hostname,
286
+ 'vim-cmd vmsvc/getallvms |'\
287
+ "grep \" #{guestvm_vmname} \"|awk '{print $1}'"
288
+ vmid = r.stdout
289
+ if (vmid == '') || (r.exit_code != 0)
290
+ raise Errors::ESXiError,
291
+ message: "Unable to register / start #{guestvm_vmname}"
292
+ end
293
+
294
+ env[:machine].id = vmid.to_i
295
+ env[:ui].info I18n.t('vagrant_vmware_esxi.vagrant_vmware_esxi_message',
296
+ message: "VMID: #{env[:machine].id}")
297
+ end
298
+ end
299
+ end
300
+ end
301
+ end
302
+ end