How do I tell vagrant to provision based on condition? I am spinning up multi VMs under a loop
Vagrantfile:
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Iterate through entries in YAML file
servers.each do |servers|
config.vm.define servers["name"] do |srv|
srv.vm.hostname = servers["name"] + DOMAIN
srv.vm.box = servers["box"]
srv.vm.network "private_network", ip: servers["ip"]
srv.vm.synced_folder ".", "/data", id: "mapping", disabled: servers["share"]
srv.vm.provider :virtualbox do |vb|
vb.memory = servers["ram"]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
end
end
end
end
I want to add something like this:
servers.each do |servers|
config.vm.define servers["name"] do |srv|
srv.vm.hostname = servers["name"] + DOMAIN
srv.vm.box = servers["box"]
srv.vm.network "private_network", ip: servers["ip"]
srv.vm.synced_folder ".", "/data", id: "mapping", disabled: servers["share"]
srv.vm.provider :virtualbox do |vb|
vb.memory = servers["ram"]
vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
end
if servers["name"] == "server1"
config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = "#{cookbooks}"
chef.add_recipe "chef_blah::server"
end
else
puts("Skipping it...")
end
end
end
But every time it executes the provision block on all the VMs
That should be srv.vm.provision, i.e. you are defining it on only that server not the root Vagrant config.
I think I found the solution. It was my mistake
instead of:
config.vm.provision :chef_solo do |chef|
I should have used
srv.vm.provision :chef_solo do |chef|
In the srv loop
Related
The following Vagrantfile configuration won't work as the next VM gets the same name as previous one. (BTW, not 100% sure, but I think this used to work in previous Vagrant versions).
Vagrant.configure(2) do |config|
config.vm.define "xfcevm" do |xfcevm|
xfcevm.vm.box = "generic/ubuntu1904"
xfcevm.vm.hostname = "xfcevm"
config.vm.provider "virtualbox" do |vb|
vb.name = "xfcevm"
end
end
config.vm.define "gnomevm" do |gnomevm|
gnomevm.vm.box = "generic/fedora30"
gnomevm.vm.hostname = "gnomevm"
config.vm.provider "virtualbox" do |vb|
vb.name = "gnomevm"
end
end
config.vm.provider "virtualbox" do |vb|
# vb.name = config.vm.hostname
vb.gui = true
vb.memory = "3072"
vb.cpus = 1
vb.customize ["modifyvm", :id, "--vram", "32"]
end
config.vm.provision "ansible" do |ansible|
ansible.verbose = "v"
ansible.compatibility_mode = "2.0"
ansible.playbook = "setup.yml"
end
config.vm.provision "ansible", run: 'always' do |ansible|
ansible.verbose = "v"
ansible.compatibility_mode = "2.0"
ansible.playbook = "tests.yml"
end
end
In the line # vb.name = config.vm.hostname, the assignment returns an object (it is printed with puts as #<Object:0x0000000001c191d8>) and I'm not familiar with Ruby and Vagrant enough to get a string attribute from it if that's even possible from that object.
P.S. a workaround (an alternative question to this one) would be to get the running VirtualBox machine name from Ansible playbook, as the goal has been calling VBoxManage on that virtual machine as local_action from inside the Ansible playbook.
You are running the virtualbox provider on the config global object.
# Wrong for multivm
# This sets a default name for all vms
config.vm.provider "virtualbox" do |vb|
vb.name = "gnomevm"
end
Simply call this on the current vm you are defining (example for gnomevm)
# Correct
# This sets the specific name for this vm only
gnomevm.vm.provider "virtualbox" do |vb|
vb.name = "gnomevm"
end
There's a multi-machine Vagrant setup (truncated here to two machines) like the following:
Vagrant.configure(2) do |config|
config.vm.define "xfcevm" do |xfcevm|
xfcevm.vm.box = "generic/ubuntu1904"
xfcevm.vm.hostname = "xfcevm"
end
config.vm.define "gnomevm" do |gnomevm|
gnomevm.vm.box = "generic/fedora30"
gnomevm.vm.hostname = "gnomevm"
end
config.vm.provider "virtualbox" do |vb|
vb.gui = true
vb.memory = "2048"
vb.cpus = 1
vb.customize ["modifyvm", :id, "--vram", "32"]
end
config.vm.provision "ansible" do |ansible|
ansible.verbose = "v"
ansible.compatibility_mode = "2.0"
ansible.playbook = "setup.yml"
end
config.vm.provision "ansible", run: 'always' do |ansible|
ansible.verbose = "v"
ansible.compatibility_mode = "2.0"
ansible.playbook = "tests.yml"
end
# halt here
end
If the tests playbook passes without errors then I want that machine to be halted just after the tests.yml playbook is finished. How I can do that from Vagrantfile or by creating another Ansible task?
You can issue a shutdown command at the end of your test playbook. It will only be played if the rest of the tasks were successful.
- name: shutdown machine
become: true
command: shutdown -h now
See shutdown --help to adapt the command to your specific need (e.g. using halt instead of poweroff)
I have this Vagrantfile. Here I defined the memory to be 2048 for all VMs. But I want my puppet master to have 4096 and agents to have 2048. How to do that?
Vagrant.configure("2") do |config|
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
config.vm.define "puppetmaster" do |pm|
pm.vm.box = "centos/7"
pm.vm.network "private_network", ip: "192.168.33.10"
pm.vm.hostname = "puppetmaster"
end
config.vm.define "puppet-agent-centos" do |pac|
pac.vm.box = "centos/7"
pac.vm.network "private_network", ip: "192.168.33.11"
pac.vm.hostname = "centos-agent"
end
config.vm.define "puppet-agent-ubuntu" do |pau|
pau.vm.box = "ubuntu/xenial64"
pau.vm.network "private_network", ip: "192.168.33.12"
pau.vm.hostname = "ubuntu-agent"
end
end
Thanks!
You can easily do that by overriding the value for a specific VM
config.vm.define "puppetmaster" do |pm|
pm.vm.box = "centos/7"
pm.vm.network "private_network", ip: "192.168.33.10"
pm.vm.hostname = "puppetmaster"
pm.vm.provider "virtualbox" do |pmv|
pmv.memory = 4096
end
end
so your whole file becomes
Vagrant.configure("2") do |config|
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
config.vm.provider "virtualbox" do |v|
v.memory = 2048
v.cpus = 2
end
config.vm.define "puppetmaster" do |pm|
pm.vm.box = "centos/7"
pm.vm.network "private_network", ip: "192.168.33.10"
pm.vm.hostname = "puppetmaster"
pm.vm.provider "virtualbox" do |pmv|
pmv.memory = 4096
end
end
config.vm.define "puppet-agent-centos" do |pac|
pac.vm.box = "centos/7"
pac.vm.network "private_network", ip: "192.168.33.11"
pac.vm.hostname = "centos-agent"
end
config.vm.define "puppet-agent-ubuntu" do |pau|
pau.vm.box = "ubuntu/xenial64"
pau.vm.network "private_network", ip: "192.168.33.12"
pau.vm.hostname = "ubuntu-agent"
end
end
when trying to use NFS with Vagrant to sync folders, on my vagrant I see the permissions as user 501 group dialout.
I fixed the issue disabling NFS and specifying a user and group manually in Vagrant file. I would like to use NFS though.
Here is my VagrantFile
$BOX = "ubuntu/xenial64"
$IP = "10.0.0.10"
$MEMORY = ENV.has_key?('VM_MEMORY') ? ENV['VM_MEMORY'] : "1024"
$CPUS = ENV.has_key?('VM_CPUS') ? ENV['VM_CPUS'] : "1"
Vagrant.configure("2") do |config|
config.vm.hostname = "name.dev"
config.vm.box = $BOX
config.vm.network :private_network, ip: $IP
config.ssh.forward_agent = true
config.vm.synced_folder ".", "/var/www/name/current", type: "nfs"
config.vm.provider "virtualbox" do |v|
v.name = "name
v.customize ["modifyvm", :id, "--cpuexecutioncap", "100"]
v.customize ["modifyvm", :id, "--memory", $MEMORY]
v.customize ["modifyvm", :id, "--cpus", $CPUS]
end
end
I've tried nfsbind but it seems that this require absolute path which I would rather avoid.
Any tips?
Thanks
I have created a service on some pods in Kubernetes. I'm able to curl the service-ip:port and I see some HTML.
I want to access the service in my browser on my own PC.
What do I have to edit in my Vagrantfile to map my vagrant internal IP on my localhost (of PC)?
This is a part of my vagrantfile (I think the part where I have to make edits)
# Finally, fall back to VirtualBox
config.vm.provider :virtualbox do |v, override|
setvmboxandurl(override, :virtualbox)
v.memory = vm_mem # v.customize ["modifyvm", :id, "--memory", vm_mem]
v.cpus = $vm_cpus # v.customize ["modifyvm", :id, "--cpus", $vm_cpus]
# Use faster paravirtualized networking
v.customize ["modifyvm", :id, "--nictype1", "virtio"]
v.customize ["modifyvm", :id, "--nictype2", "virtio"]
end
end
# Kubernetes master
config.vm.define "master" do |c|
customize_vm c, $vm_master_mem
if ENV['KUBE_TEMP'] then
script = "#{ENV['KUBE_TEMP']}/master-start.sh"
c.vm.provision "shell", run: "always", path: script
end
c.vm.network "private_network", ip: "#{$master_ip}"
end
# Kubernetes node
$num_node.times do |n|
node_vm_name = "node-#{n+1}"
node_prefix = ENV['INSTANCE_PREFIX'] || 'kubernetes' # must mirror default in cluster/vagrant/config-default.sh
node_hostname = "#{node_prefix}-#{node_vm_name}"
config.vm.define node_vm_name do |node|
customize_vm node, $vm_node_mem
node_ip = $node_ips[n]
if ENV['KUBE_TEMP'] then
script = "#{ENV['KUBE_TEMP']}/node-start-#{n}.sh"
node.vm.provision "shell", run: "always", path: script
end
node.vm.network "private_network", ip: "#{node_ip}"
end
end
I tried to change node.vm.network "private_network", ip: "#{node_ip}" in node.vm.network "private_network", ip: "192.xx.xx.xx"but I'm not able to reload my vagrant:
/opt/vagrant/embedded/lib/ruby/2.2.0/ipaddr.rb:559:in `in6_addr': invalid address (IPAddr::InvalidAddressError)
Your service needs to be of type NodePort to be reached on the IP of the vagrant VM. For example if your pods are started by a replication controller. Create the services with:
kubectl expose rc foobar --type=NodePort --port=80
This will return a random port. Open your browser on your Vagrant node VM at that port and you will reach your service.