Skip to content

Commit e8672e2

Browse files
committed
Fix kubernetes#2741. Add support for alternate Vagrant providers: VMWare Fusion, VMWare Workstation, and Parallels.
1 parent 3bc42f1 commit e8672e2

File tree

4 files changed

+326
-131
lines changed

4 files changed

+326
-131
lines changed

Vagrantfile

+127-20
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,46 @@ $minion_ips = $num_minion.times.collect { |n| $minion_ip_base + "#{n+3}" }
2727
# Determine the OS platform to use
2828
$kube_os = ENV['KUBERNETES_OS'] || "fedora"
2929

30-
# Check if we already have kube box
31-
$kube_box_url = ENV['KUBERNETES_BOX_URL'] || "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_fedora-20_chef-provisionerless.box"
32-
33-
# OS platform to box information
34-
$kube_box = {
35-
"fedora" => {
36-
"name" => "fedora20",
37-
"box_url" => $kube_box_url
30+
# To override the vagrant provider, use (e.g.):
31+
# KUBERNETES_PROVIDER=vagrant VAGRANT_DEFAULT_PROVIDER=... .../cluster/kube-up.sh
32+
# To override the box, use (e.g.):
33+
# KUBERNETES_PROVIDER=vagrant KUBERNETES_BOX_NAME=... .../cluster/kube-up.sh
34+
# You can specify a box version:
35+
# KUBERNETES_PROVIDER=vagrant KUBERNETES_BOX_NAME=... KUBERNETES_BOX_VERSION=... .../cluster/kube-up.sh
36+
# You can specify a box location:
37+
# KUBERNETES_PROVIDER=vagrant KUBERNETES_BOX_NAME=... KUBERNETES_BOX_URL=... .../cluster/kube-up.sh
38+
# KUBERNETES_BOX_URL and KUBERNETES_BOX_VERSION will be ignored unless
39+
# KUBERNETES_BOX_NAME is set
40+
41+
# Default OS platform to provider/box information
42+
$kube_provider_boxes = {
43+
:parallels => {
44+
'fedora' => {
45+
# :box_url and :box_version are optional (and mutually exclusive);
46+
# if :box_url is omitted the box will be retrieved by :box_name (and
47+
# :box_version if provided) from
48+
# http://atlas.hashicorp.com/boxes/search (formerly
49+
# http://vagrantcloud.com/); this allows you override :box_name with
50+
# your own value so long as you provide :box_url; for example, the
51+
# "official" name of this box is "rickard-von-essen/
52+
# opscode_fedora-20", but by providing the URL and our own name, we
53+
# make it appear as yet another provider under the "kube-fedora20"
54+
# box
55+
:box_name => 'kube-fedora20',
56+
:box_url => 'https://atlas.hashicorp.com/rickard-von-essen/boxes/opscode_fedora-20/versions/0.4.0/providers/parallels.box'
57+
}
58+
},
59+
:virtualbox => {
60+
'fedora' => {
61+
:box_name => 'kube-fedora20',
62+
:box_url => 'http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_fedora-20_chef-provisionerless.box'
63+
}
64+
},
65+
:vmware_desktop => {
66+
'fedora' => {
67+
:box_name => 'kube-fedora20',
68+
:box_url => 'http://opscode-vm-bento.s3.amazonaws.com/vagrant/vmware/opscode_fedora-20-i386_chef-provisionerless.box'
69+
}
3870
}
3971
}
4072

@@ -54,16 +86,88 @@ end
5486
# In Fedora VM, tmpfs device is mapped to /tmp. tmpfs is given 50% of RAM allocation.
5587
# When doing Salt provisioning, we copy approximately 200MB of content in /tmp before anything else happens.
5688
# This causes problems if anything else was in /tmp or the other directories that are bound to tmpfs device (i.e /run, etc.)
57-
$vm_mem = (ENV['KUBERNETES_MEMORY'] || 1024).to_i
89+
$vm_master_mem = (ENV['KUBERNETES_MASTER_MEMORY'] || ENV['KUBERNETES_MEMORY'] || 1024).to_i
90+
$vm_minion_mem = (ENV['KUBERNETES_MINION_MEMORY'] || ENV['KUBERNETES_MEMORY'] || 1024).to_i
5891

5992
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
60-
def customize_vm(config)
61-
config.vm.box = $kube_box[$kube_os]["name"]
62-
config.vm.box_url = $kube_box[$kube_os]["box_url"]
93+
def setvmboxandurl(config, provider)
94+
if ENV['KUBERNETES_BOX_NAME'] then
95+
config.vm.box = ENV['KUBERNETES_BOX_NAME']
6396

64-
config.vm.provider :virtualbox do |v|
65-
v.customize ["modifyvm", :id, "--memory", $vm_mem]
66-
v.customize ["modifyvm", :id, "--cpus", $vm_cpus]
97+
if ENV['KUBERNETES_BOX_URL'] then
98+
config.vm.box_url = ENV['KUBERNETES_BOX_URL']
99+
end
100+
101+
if ENV['KUBERNETES_BOX_VERSION'] then
102+
config.vm.box_version = ENV['KUBERNETES_BOX_VERSION']
103+
end
104+
else
105+
config.vm.box = $kube_provider_boxes[provider][$kube_os][:box_name]
106+
107+
if $kube_provider_boxes[provider][$kube_os][:box_url] then
108+
config.vm.box_url = $kube_provider_boxes[provider][$kube_os][:box_url]
109+
end
110+
111+
if $kube_provider_boxes[provider][$kube_os][:box_version] then
112+
config.vm.box_version = $kube_provider_boxes[provider][$kube_os][:box_version]
113+
end
114+
end
115+
end
116+
117+
def customize_vm(config, vm_mem)
118+
# Try VMWare Fusion first (see
119+
# https://docs.vagrantup.com/v2/providers/basic_usage.html)
120+
config.vm.provider :vmware_fusion do |v, override|
121+
setvmboxandurl(override, :vmware_desktop)
122+
v.vmx['memsize'] = vm_mem
123+
v.vmx['numvcpus'] = $vm_cpus
124+
end
125+
126+
# Then try VMWare Workstation
127+
config.vm.provider :vmware_workstation do |v, override|
128+
setvmboxandurl(override, :vmware_desktop)
129+
v.vmx['memsize'] = vm_mem
130+
v.vmx['numvcpus'] = $vm_cpus
131+
end
132+
133+
# Then try Parallels
134+
config.vm.provider :parallels do |v, override|
135+
setvmboxandurl(override, :parallels)
136+
v.memory = vm_mem # v.customize ['set', :id, '--memsize', vm_mem]
137+
v.cpus = $vm_cpus # v.customize ['set', :id, '--cpus', $vm_cpus]
138+
139+
# Don't attempt to update the Parallels tools on the image (this can
140+
# be done manually if necessary)
141+
v.update_guest_tools = false # v.customize ['set', :id, '--tools-autoupdate', 'off']
142+
143+
# Set up Parallels folder sharing to behave like VirtualBox (i.e.,
144+
# mount the current directory as /vagrant and that's it)
145+
v.customize ['set', :id, '--shf-guest', 'off']
146+
v.customize ['set', :id, '--shf-guest-automount', 'off']
147+
v.customize ['set', :id, '--shf-host', 'on']
148+
149+
# Remove all auto-mounted "shared folders"; the result seems to
150+
# persist between runs (i.e., vagrant halt && vagrant up)
151+
override.vm.provision :shell, :inline => (%q{
152+
set -ex
153+
if [ -d /media/psf ]; then
154+
for i in /media/psf/*; do
155+
if [ -d "${i}" ]; then
156+
umount "${i}" || true
157+
rmdir -v "${i}"
158+
fi
159+
done
160+
rmdir -v /media/psf
161+
fi
162+
exit
163+
}).strip
164+
end
165+
166+
# Finally, fall back to VirtualBox
167+
config.vm.provider :virtualbox do |v, override|
168+
setvmboxandurl(override, :virtualbox)
169+
v.memory = vm_mem # v.customize ["modifyvm", :id, "--memory", vm_mem]
170+
v.cpus = $vm_cpus # v.customize ["modifyvm", :id, "--cpus", $vm_cpus]
67171

68172
# Use faster paravirtualized networking
69173
v.customize ["modifyvm", :id, "--nictype1", "virtio"]
@@ -73,7 +177,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
73177

74178
# Kubernetes master
75179
config.vm.define "master" do |c|
76-
customize_vm c
180+
customize_vm c, $vm_master_mem
77181
if ENV['KUBE_TEMP'] then
78182
script = "#{ENV['KUBE_TEMP']}/master-start.sh"
79183
c.vm.provision "shell", run: "always", path: script
@@ -84,17 +188,20 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
84188

85189
# Kubernetes minion
86190
$num_minion.times do |n|
87-
config.vm.define "minion-#{n+1}" do |minion|
88-
customize_vm minion
191+
minion_vm_name = "minion-#{n+1}"
192+
minion_prefix = ENV['INSTANCE_PREFIX'] || 'kubernetes' # must mirror default in cluster/vagrant/config-default.sh
193+
minion_hostname = "#{minion_prefix}-#{minion_vm_name}"
194+
195+
config.vm.define minion_vm_name do |minion|
196+
customize_vm minion, $vm_minion_mem
89197

90-
minion_index = n+1
91198
minion_ip = $minion_ips[n]
92199
if ENV['KUBE_TEMP'] then
93200
script = "#{ENV['KUBE_TEMP']}/minion-start-#{n}.sh"
94201
minion.vm.provision "shell", run: "always", path: script
95202
end
96203
minion.vm.network "private_network", ip: "#{minion_ip}"
97-
minion.vm.hostname = "#{ENV['INSTANCE_PREFIX']}-minion-#{minion_index}"
204+
minion.vm.hostname = minion_hostname
98205
end
99206
end
100207
end

cluster/vagrant/util.sh

+55-1
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,62 @@ function detect-minions {
3333
# Verify prereqs on host machine Also sets exports USING_KUBE_SCRIPTS=true so
3434
# that our Vagrantfile doesn't error out.
3535
function verify-prereqs {
36-
for x in vagrant VBoxManage; do
36+
for x in vagrant; do
3737
if ! which "$x" >/dev/null; then
3838
echo "Can't find $x in PATH, please fix and retry."
3939
exit 1
4040
fi
4141
done
4242

43+
local vagrant_plugins=$(vagrant plugin list | sed '-es% .*$%%' '-es% *% %g' | tr ' ' $'\n')
44+
local providers=(
45+
# Format is:
46+
# provider_ctl_executable vagrant_provider_name vagrant_provider_plugin_re
47+
# either provider_ctl_executable or vagrant_provider_plugin_re can
48+
# be blank (i.e., '') if none is needed by Vagrant (see, e.g.,
49+
# virtualbox entry)
50+
vmrun vmware_fusion vagrant-vmware-fusion
51+
vmrun vmware_workstation vagrant-vmware-workstation
52+
prlctl parallels vagrant-parallels
53+
VBoxManage virtualbox ''
54+
)
55+
local provider_found=''
56+
local provider_bin
57+
local provider_name
58+
local provider_plugin_re
59+
60+
while [ "${#providers[@]}" -gt 0 ]; do
61+
provider_bin=${providers[0]}
62+
provider_name=${providers[1]}
63+
provider_plugin_re=${providers[2]}
64+
providers=("${providers[@]:3}")
65+
66+
# If the provider is explicitly set, look only for that provider
67+
if [ -n "${VAGRANT_DEFAULT_PROVIDER:-}" ] \
68+
&& [ "${VAGRANT_DEFAULT_PROVIDER}" != "${provider_name}" ]; then
69+
continue
70+
fi
71+
72+
if ([ -z "${provider_bin}" ] \
73+
|| which "${provider_bin}" >/dev/null 2>&1) \
74+
&& ([ -z "${provider_plugin_re}" ] \
75+
|| [ -n "$(echo "${vagrant_plugins}" | grep -E "^${provider_plugin_re}$")" ]); then
76+
provider_found="${provider_name}"
77+
# Stop after finding the first viable provider
78+
break
79+
fi
80+
done
81+
82+
if [ -z "${provider_found}" ]; then
83+
if [ -n "${VAGRANT_DEFAULT_PROVIDER}" ]; then
84+
echo "Can't find the necessary components for the ${VAGRANT_DEFAULT_PROVIDER} vagrant provider, please fix and retry."
85+
else
86+
echo "Can't find the necessary components for any viable vagrant providers (e.g., virtualbox), please fix and retry."
87+
fi
88+
89+
exit 1
90+
fi
91+
4392
# Set VAGRANT_CWD to KUBE_ROOT so that we find the right Vagrantfile no
4493
# matter what directory the tools are called from.
4594
export VAGRANT_CWD="${KUBE_ROOT}"
@@ -89,6 +138,7 @@ function create-provision-scripts {
89138
echo "DNS_REPLICAS='${DNS_REPLICAS:-}'"
90139
echo "RUNTIME_CONFIG='${RUNTIME_CONFIG:-}'"
91140
echo "ADMISSION_CONTROL='${ADMISSION_CONTROL:-}'"
141+
echo "VAGRANT_DEFAULT_PROVIDER='${VAGRANT_DEFAULT_PROVIDER:-}'"
92142
grep -v "^#" "${KUBE_ROOT}/cluster/vagrant/provision-master.sh"
93143
grep -v "^#" "${KUBE_ROOT}/cluster/vagrant/provision-network.sh"
94144
) > "${KUBE_TEMP}/master-start.sh"
@@ -109,13 +159,17 @@ function create-provision-scripts {
109159
echo "MINION_CONTAINER_SUBNETS=(${MINION_CONTAINER_SUBNETS[@]})"
110160
echo "CONTAINER_SUBNET='${CONTAINER_SUBNET}'"
111161
echo "DOCKER_OPTS='${EXTRA_DOCKER_OPTS-}'"
162+
echo "VAGRANT_DEFAULT_PROVIDER='${VAGRANT_DEFAULT_PROVIDER:-}'"
112163
grep -v "^#" "${KUBE_ROOT}/cluster/vagrant/provision-minion.sh"
113164
grep -v "^#" "${KUBE_ROOT}/cluster/vagrant/provision-network.sh"
114165
) > "${KUBE_TEMP}/minion-start-${i}.sh"
115166
done
116167
}
117168

118169
function verify-cluster {
170+
# TODO: How does the user know the difference between "tak[ing] some
171+
# time" and "loop[ing] forever"? Can we give more specific feedback on
172+
# whether "an error" has occurred?
119173
echo "Each machine instance has been created/updated."
120174
echo " Now waiting for the Salt provisioning process to complete on each machine."
121175
echo " This can take some time based on your network, disk, and cpu speed."

0 commit comments

Comments
 (0)