I'm using Vagrant to create three hosts. I want to give them the name node01, node02 and node03.
Using the following Vagrantfile:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.define "node01" do |node01|
node01.vm.box = "ubuntu/trusty64"
node01.vm.hostname = "node01"
end
config.vm.define "node02" do |node02|
node02.vm.box = "ubuntu/trusty64"
node02.vm.hostname = "node02"
end
config.vm.define "node03" do |node03|
node03.vm.box = "ubuntu/trusty64"
node03.vm.hostname = "node03"
end
config.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
end
end
On virtualbox, the names are cryptic (like ubuntu-3nodes-node01-timestamp ...). How can I ensure they are just called node01, node02 and node03
I know I can do in the config.vm.provider "virtualbox" but I would ideally do it in the config.vm.define "node01" sections
you can do something like this
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
(1..3).each do |i|
config.vm.define "node0#{i}" do |node|
config.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
vb.name = "node0#{i}"
end
node.vm.hostname = "node0#{i}"
end
end
end
This is some ruby to loop on the node.
the box if its the same in all machine can be defined at the upper block level
You must make the name of the name of VirtualBox VM in the virtualbox block as it depends on virtualbox (vagrant can manage other provider and this would be different)
You can also separate loop from define node method.
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure(2) do |config|
config.vm.box = "ubuntu/trusty64"
def define_node(config, node_number)
config.vm.define "node0#{node_number}" do |node|
node.vm.hostname = "node0#{node_number}"
node.vm.provider "virtualbox" do |vb|
vb.memory = "1024"
vb.name = "node0#{node_number}"
end
end
end
for node_number in 1..3
define_node config, node_number
end
end
Related
Im struggling with this Vagrantfile. My goal is to set up two virtual machines using Vagrant technology and also utilize Ansible to deploy a certain task in each machine after they had been created.
But how can execute provision with ansible after the two machines had been created successfuly?
# -*- mode: ruby -*-
# vi: set ft=ruby :
# variables
BOX_NAME = "debian/buster64"
PRIVATE_KEY_PATH_CONTROLLER = "~/.ssh/id_rsa"
PRIVATE_KEY_PATH_VAGRANT = "~/.vagrant.d/insecure_private_key"
PUBLIC_KEY_PATH_CONTROLLER = "~/.ssh/id_rsa.pub"
AUTHORIZED_KEYS_PATH = "~/.ssh/authorized_keys"
Vagrant.configure("2") do |config|
# configuracion general
config.vm.box = BOX_NAME
config.ssh.insert_key = false
config.ssh.private_key_path = [PRIVATE_KEY_PATH_CONTROLLER, PRIVATE_KEY_PATH_VAGRANT]
config.vm.provision "file", source: PUBLIC_KEY_PATH_CONTROLLER, destination: AUTHORIZED_KEYS_PATH
config.vm.synced_folder "./shared", "/vagrant"
# configuracion nodo 1
config.vm.define "nodo_uno" do |nodo|
nodo.vm.hostname = "nodo1"
nodo.vm.network "private_network", ip: "192.168.50.10"
nodo.vm.provider "virtualbox" do |vb|
vb.name = "nodo1(50.10)"
vb.memory = 512
vb.cpus = 1
end
end
# configuracion nodo 2
config.vm.define "nodo_dos" do |nodo|
nodo.vm.hostname = "nodo2"
nodo.vm.network "private_network", ip: "192.168.50.20"
nodo.vm.provider "virtualbox" do |vb|
vb.name = "nodo2(50.20)"
vb.memory = 512
vb.cpus = 1
end
end
# if nodo = "nodo_dos"
config.vm.provision "ansible" do |ansible|
# ansible.groups = {
# "nodo_uno" => ["nodos"],
# "nodo_dos" => ["nodos"]
# }
ansible.inventory_path = "./hosts"
ansible.limit = "nodos"
ansible.playbook = "grupos_usuarios.yml"
ansible.become = true
end
end
nodos is a group that involves nodo_uno and nodo_dos
so when I run vagrant up, ansible throws me an error because of noo2 has not been created yet. so it can't provision it.
I know I can use "vagrant up --no-provision" and then "vagant provision" but what I want is to avoid this system and use some conditional statement in my vagrantfile that triggers my playbook once node2 had been successfuly set up. Sorry for my bad english.
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
My configuration is below and the boxes were working fine:
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
(1..4).each do |i|
config.vm.define "node#{i}", autostart:true do |node|
config.vm.box = "ubuntu/trusty64"
config.vm.hostname="node#{i}"
config.vm.network "private_network", ip: "192.168.59.#{i}"
config.vm.synced_folder "~/Documents/csunp/unp", "/vagrant/unp"
config.vm.provider "virtualbox" do |v|
v.name = "node#{i}"
v.memory = 512
v.cpus = 1
end
end
end
end
But once I power down my computer, I can't go back any more.
Running vagrant up, I got the error below:
Bringing machine 'node1' up with 'virtualbox' provider...
Bringing machine 'node2' up with 'virtualbox' provider...
Bringing machine 'node3' up with 'virtualbox' provider...
Bringing machine 'node4' up with 'virtualbox' provider...
There are errors in the configuration of this machine. Please fix
the following errors and try again:
vm:
* A box must be specified.
What's wrong with that? Thanks in advance.
hum your Vagrantfile is not very well written, you created a loop to create 4 instances with a node variable but still uses config.vm
If you want to keep simple, change to
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
(1..4).each do |i|
config.vm.define "node#{i}", autostart:true do |node|
node.vm.box = "ubuntu/trusty64"
node.vm.hostname="node#{i}"
node.vm.network "private_network", ip: "192.168.59.#{i}"
node.vm.synced_folder "~/Documents/csunp/unp", "/vagrant/unp"
node.vm.provider "virtualbox" do |v|
v.name = "node#{i}"
v.memory = 512
v.cpus = 1
end
end
end
end
If you're using the same box for all 4 VMs, you can write as
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/trusty64"
config.vm.synced_folder "~/Documents/csunp/unp", "/vagrant/unp"
(1..4).each do |i|
config.vm.define "node#{i}", autostart:true do |node|
node.vm.hostname="node#{i}"
node.vm.network "private_network", ip: "192.168.59.#{i}"
node.vm.provider "virtualbox" do |v|
v.name = "node#{i}"
v.memory = 512
v.cpus = 1
end
end
end
end
I already found this question about how to pass parameters to the Vagrantfile environment, but it seems that it doesn't work on windows. In fact if I try to run:
SERV=client vagrant up
With this Vagrantfile:
# -*- mode: ruby -*-
# # vi: set ft=ruby :
# Specify minimum Vagrant version and Vagrant API version
Vagrant.require_version ">= 1.6.0"
VAGRANTFILE_API_VERSION = "2"
# Require YAML module
require 'yaml'
# Read YAML file with box details
servers = YAML.load_file('RaftFS/servers.yaml')
# Create boxes
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# Create servers
# Iterate through entries in YAML file
if ENV['SERV'] != "client"
servers.each do |key,value|
if key == ENV['SERV']
config.vm.define key do |srv|
srv.vm.box = value['box']
#srv.vm.network "private_network", ip: value['ip']
if value['ip'] != ''
srv.vm.provision "shell", inline: "echo NO IP ADDRESS"
srv.vm.network :public_network, bridge:'wlan0'
else
srv.vm.network :public_network, ip:value['ip'] ,bridge:'wlan0'
srv.vm.provision "shell", inline: "echo IP FOUND FOR"
end
srv.vm.hostname=key
srv.vm.synced_folder ".", "/vagrant" , disabled:true
srv.vm.synced_folder "ServersFS/"+key+"/", "/vagrant/ServersFS" , create: true
srv.vm.synced_folder "./RaftFS", "/vagrant/RaftFS"
srv.vm.provision :shell do |shell|
shell.path = "provision.sh"
shell.args = "'TRUE'"
end
srv.vm.provider :virtualbox do |vb|
vb.name = key
vb.memory = value['ram']
end
end
end
end
else
config.vm.define "client" do |cln|
cln.vm.box = "hashicorp/precise32"
cln.vm.network :public_network, bridge:'wlan0', ip:"192.168.1.140"
cln.vm.hostname="client"
cln.vm.provision :shell do |shell|
shell.path = "provision.sh"
shell.args = "'FALSE'"
end
end
end
end
Windows prompt doesn't recognize SERV=client as valid command. I'm sorry for the question, but I'm totally new with both Vagrant and Ruby (and I usually program on Linux)!
So I stumbled on this issue as well. To pass parameters from command prompt to Vagrantfile it should pass as an environment variable, and you can do it in one line:
set "SERV=client" && vagrant up
In the Vagrantfile, you then can access the parameter as ENV['SERV']
A heads-up is that the environment variable will still exist in the environment after vagrant has finished.
First off here's the error I'm getting:
There are errors in the configuration of this machine. Please fix
the following errors and try again:
chef client provisioner:
* Chef server URL must be populated.
* Validation key path must be valid path to your chef server validation key.
The chef server URL does appear to be populated, and the validation key path is valid.
I've got 3 Vagrantfiles in effect, and I'm using the documentation to try to get the order correct.
This works fine when I stick everything in one Vagrantfile in the project directory, but I want to set defaults and not have to copy paste everything.
1) The Vagrantfile packaged with the box:
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.provider :vsphere do |vsphere|
vsphere.host = 'vsphereserver.example.com'
vsphere.compute_resource_name = 'TestDev'
vsphere.user = 'vagrantadmin'
vsphere.password = 'password'
vsphere.insecure = true
end
config.ssh.username = 'auto'
config.ssh.private_key_path = '~/.vagrant.d/id_rsa'
end
2) The Vagrantfile in my home directory (~/.vagrant.d):
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = 'vsphere'
config.vm.provider :vsphere do |vsphere|
vsphere.template_name = 'vagrantchefnode'
end
config.vm.provision "chef_client" do |chef|
chef.add_role "base"
chef.provisioning_path = "/etc/chef"
chef.chef_server_url = "https://chefserver.example.com"
chef.validation_key_path = "/home/user/.vagrant.d/chef/validation.pem"
chef.client_key_path = "/etc/chef/client.pem"
chef.validation_client_name = "chef-validator"
chef.custom_config_path = "/home/user/.vagrant.d/Vagrantfile.chef"
chef.delete_node = true
chef.delete_client = true
end
end
3) Vagrantfile from the project directory (~/.vagrant.d/boxes/chefnode1):
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.provider :vsphere do |vsphere|
# vsphere.template_name = 'chefnode'
vsphere.customization_spec_name = 'chefnode1'
vsphere.name = 'chefnode1'
end
config.vm.provision "chef_client" do |chef|
chef.node_name = "chefnode1"
chef.add_role "test"
end
end
Is it overwriting the entire chef_client configuration somehow? If so, how do I make it stick and merge the way it's supposed to?
Update:
I've got something working with Tejay's answer and this doc, but it requires translating to a different syntax, and I can't figure out how to get methods like add_role translated. Here's what I've got:
2)
config.vm.provision "chef_client",
id: "chef",
provisioning_path: "/etc/chef",
chef_server_url: "https://chefserver.example.com",
validation_key_path: "/home/user/.vagrant.d/chef/validation.pem",
client_key_path: "/etc/chef/client.pem",
validation_client_name: "chef-validator",
custom_config_path: "/home/user/.vagrant.d/Vagrantfile.chef",
delete_node: true,
delete_client: true
3)
config.vm.provision "chef_client",
id: "chef",
node_name: "chefnode1"
So this brings the machine up but I can't specify a run_list.
You are actually creating two provisioners, one in each file, and so the provisioner in your project directory does not have a URL or validation key. Vagrant's documentation explains that you need to use an id in order to modify an existing provider. Take a look at the section "OVERRIDING PROVISIONER SETTINGS" on this page:
https://docs.vagrantup.com/v2/provisioning/basic_usage.html
So try this (not tested):
The Vagrantfile in my home directory (~/.vagrant.d):
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.box = 'vsphere'
config.vm.provider :vsphere do |vsphere|
vsphere.template_name = 'vagrantchefnode'
end
config.vm.provision("chef_client", id: 'someID') do |chef|
chef.add_role "base"
chef.provisioning_path = "/etc/chef"
chef.chef_server_url = "https://chefserver.example.com"
chef.validation_key_path = "/home/user/.vagrant.d/chef/validation.pem"
chef.client_key_path = "/etc/chef/client.pem"
chef.validation_client_name = "chef-validator"
chef.custom_config_path = "/home/user/.vagrant.d/Vagrantfile.chef"
chef.delete_node = true
chef.delete_client = true
end
end
Vagrantfile from the project directory (~/.vagrant.d/boxes/chefnode1):
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.provider :vsphere do |vsphere|
# vsphere.template_name = 'chefnode'
vsphere.customization_spec_name = 'chefnode1'
vsphere.name = 'chefnode1'
end
config.vm.provision("chef_client", id: 'someID') do |chef|
chef.node_name = "chefnode1"
chef.add_role "test"
end
end