Vagrant Config Error - “A box must be specified.” - vagrant

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

Related

How execute a playbook within Vagrantfile with a certain condition?

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.

Vagrantfile: name virtual hosts in single file

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

Vagrant: passing parameters in windows

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.

Can the vagrant hostsupdater plugin add a hosts entry for a public network?

Vagrant version: 1.6.3
Vagrant plugins installed:
vagrant-hostsupdater (0.0.11)
vagrant-login (1.0.1, system)
vagrant-share (1.1.0, system)
vagrant-vbguest (0.10.0)
vagrant-vbox-snapshot (0.0.5)
My vagrant file defines a private and public network - The hosts updater plugin adds an /etc/hosts entry for the private network but not the public network - any solution to this?
(other than manually entering it - i know its a static IP but i am lazy) - thanks
my Vagrantfile follows (which I am proud of, works perfectly) ...
# -*- mode: ruby -*-
# vi: set ft=ruby :
VAGRANTFILE_API_VERSION = "2"
IP_END = 88
HTTP_PORT = 8888
BOX_NAME = "hashicorp/precise32"
HOST_NAME = "precise32.com"
GUI = false
# vagrantup.com
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = BOX_NAME
config.vm.network "private_network", ip: "192.168.56.#{IP_END}"
config.vm.network "public_network", bridge: "wlan0", ip: "192.168.1.#{IP_END}"
config.vm.network "forwarded_port", guest: 80, host: HTTP_PORT
config.vm.hostname = HOST_NAME
# 'vagrant box outdated' forces a check update
config.vm.box_check_update = true
config.ssh.forward_agent = false
# config.vm.synced_folder "../data", "/vagrant_data"
config.vm.provider "virtualbox" do |vb|
vb.gui = GUI
vb.customize ["modifyvm", :id, "--clipboard", "bidirectional"]
vb.customize ["modifyvm", :id, "--draganddrop", "bidirectional"]
end
config.vm.provision "puppet" do |puppet|
puppet.manifests_path = "manifests"
puppet.manifest_file = "site.pp"
end
end
It looks like someone already submitted a pull request to the hostsupdater plugin: https://github.com/cogitatio/vagrant-hostsupdater/pull/47
I don't know how actively maintained this plugin is (last commit was October 2013). At a minimum you could implement the same code change from that pull request in your local copy of the plugin.

Multiple providers in a single vagrant file?

I've got a vagrant file that builds a local VM. I want to add the EC2 provider and have the option of either provisioning a local VM or one on EC2.
Can I create configs for multiple providers in the same Vagrantfile and somehow choose which to run when I do vagrant up?
You can use a multi-vm environment, where every VM can be provisioned with a different provider and you can choose on commandline which one you want to vagrant up <machine>.
add box for each provider
> vagrant box add precise64 http://file.vagrantup.com/precise64.box
> vagrant box add precise64 http://file.vagrantup.com/precise64_vmware_fusion.box
and your Vagrantfile should look like
Vagrant.configure(2) do |config|
config.vm.box="precise64"
config.vm.provider "virtualbox" do |v|
v.customize ["modifyvm", :id, "--memory", "2048"]
end
config.vm.provider "vmware_fusion" do |v|
v.vmx["memsize"] = "2048"
end
end
then create on each provider using following commands
> vagrant up --provider=virtualbox
> vagrant up --provider=vmware_fusion
You can choose which provider you want to run by --provider parameter.
Here is ruby code in Vagrantfile which can run different VM depending which provider you have chosen:
require 'getoptlong'
# Parse CLI arguments.
opts = GetoptLong.new(
[ '--provider', GetoptLong::OPTIONAL_ARGUMENT ],
)
provider='virtualbox'
begin
opts.each do |opt, arg|
case opt
when '--provider'
provider=arg
end # case
end # each
rescue
end
# Vagrantfile API/syntax version.
Vagrant.configure(2) do |config|
config.vm.hostname = "vagrant"
config.vm.define "default-#{provider}"
config.vm.provider "virtualbox" do |vbox, override|
vbox.customize ['modifyvm', :id, '--natdnshostresolver1', 'on']
vbox.name = "test.local"
override.vm.box = "ubuntu/wily64"
override.vm.network "private_network", ip: "192.168.22.22"
end
config.vm.provider :aws do |aws, override|
aws.ami = "ami-7747d01e"
aws.instance_type = "m3.medium"
override.vm.box = "dummy"
override.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
override.ssh.username = "ubuntu"
end
end
So by the default provider is virtualbox, but you can specify from the command line, like:
vagrant up --provider=aws
To run VM locally you can run:
vagrant up --provider=virtualbox
and if you'd like to run VM using different provider then you can use:
vagrant up --provider=aws
However, remember that you have to install appropriate provider plugin before you will use it.
Please check this gist posted by #tknerr which works with all providers such as virtualbox, AWS and managed in combination with the vagrant-omnibus plugin. Here is the code from Vagrantfile:
#
# Vagrantfile for testing
#
Vagrant::configure("2") do |config|
# the Chef version to use
config.omnibus.chef_version = "11.4.4"
def configure_vbox_provider(config, name, ip, memory = 384)
config.vm.provider :virtualbox do |vbox, override|
# override box url
override.vm.box = "opscode_ubuntu-13.04_provisionerless"
override.vm.box_url = "https://opscode-vm.s3.amazonaws.com/vagrant/opscode_ubuntu-13.04_provisionerless.box"
# configure host-only network
override.vm.hostname = "#{name}.local"
override.vm.network :private_network, ip: ip
# enable cachier for local vbox vms
override.cache.auto_detect = true
# virtualbox specific configuration
vbox.customize ["modifyvm", :id,
"--memory", memory,
"--name", name
]
end
end
def configure_aws_provider(config)
config.vm.provider :aws do |aws, override|
# use dummy box
override.vm.box = "aws_dummy_box"
override.vm.box_url = "https://github.com/mitchellh/vagrant-aws/raw/master/dummy.box"
# override ssh user and private key
override.ssh.username = "ubuntu"
override.ssh.private_key_path = "#{ENV['HOME']}/.ssh/mccloud_rsa"
# aws specific settings
aws.access_key_id = "XXXX"
aws.secret_access_key = "XXXXX"
aws.ami = "ami-524e4726"
aws.region = "eu-west-1"
aws.availability_zone = "eu-west-1c"
aws.instance_type = "m1.small"
aws.security_groups = [ "mccloud", "http" ]
aws.keypair_name = "mccloud-key-tlc"
end
end
def configure_managed_provider(config, server)
config.vm.provider :managed do |managed, override|
# use dummy box
override.vm.box = "managed_dummy_box"
override.vm.box_url = "https://github.com/tknerr/vagrant-managed-servers/raw/master/dummy.box"
# link with this server
managed.server = server
end
end
#
# define a separate VMs for the 3 providers (vbox, aws, managed)
# because with Vagrant 1.2.2 you can run a VM with only one provider at once
#
[:aws, :vbox, :esx].each do |provider|
#
# Sample VM per provider
#
config.vm.define :"sample-app-#{provider}" do | sample_app_config |
case provider
when :vbox
configure_vbox_provider(sample_app_config, "sample-app", "33.33.40.10")
when :aws
configure_aws_provider(sample_app_config)
when :esx
configure_managed_provider(sample_app_config, "33.33.77.10")
end
sample_app_config.vm.provision :chef_solo do |chef|
chef.cookbooks_path = [ './cookbooks/sample-app-0.1.0' ]
chef.add_recipe "sample-app"
chef.json = {
:sample_app => {
:words_of_wisdom => "Vagrant on #{provider} Rocks!"
}
}
end
end
end
end
From the Vagrant docs:
Multiple config.vm.provision methods can be used to define multiple provisioners. These provisioners will be run in the order they're defined.
eg.:
First install puppet in the machine and then run some puppet manifests:
$script = "
wget http://apt.puppetlabs.com/puppetlabs-release-precise.deb
sudo dpkg -i puppetlabs-release-precise.deb
sudo apt-get update
sudo aptitude -yy install puppet
"
config.vm.provision "shell", inline: $script
config.vm.provision "puppet" do |puppet|
puppet.manifests_path = "manifest/puppet"
puppet.manifest_file = "init.pp"
end
config.vm.provision "shell", inline: "echo Second shell provisioner"
Yes, you can specify multiple machines by using the config.vm.define method call, for example:
Vagrant.configure("2") do |config|
config.vm.provision "shell", inline: "echo Hello"
config.vm.define "web" do |web|
web.vm.box = "apache"
end
config.vm.define "db" do |db|
db.vm.box = "mysql"
end
end
See: Defining multiple machines at Vagranup Docs and Providers

Resources