vagrant-hostmanager (1.8.6) error when updating guest hosts? - vagrant

I have vagrant-hostmanager 1.8.6 installed, and when I run vagrant hostmanager I end up with the following error:
[vagrant-hostmanager:guest] Updating hosts file on the virtual machine puppet_server...
sh: 1: Syntax error: "(" unexpected
...and the /etc/hosts file is not updated. Is there a way to fix this?
Here is my VagrantFile:
Vagrant.configure(2) do |config|
config.vm.box = "blah/turnkey-lamp-14.2"
config.vm.provider "virtualbox" do |vb|
vb.cpus = 2
vb.gui = true
end
config.vm.boot_timeout = 10000
config.vm.network "private_network", type: "dhcp"
#config.vm.provision :hostmanager
config.ssh.insert_key = false
#config.ssh.private_key_path = "/mnt/vm_lab/vagrant_box_storage/.vagrant.d/insecure_private_key"
config.ssh.forward_agent = true
config.hostmanager.enabled = true
config.hostmanager.manage_guest = true
#config.hostmanager.manage_host = true
config.hostmanager.ip_resolver = proc do |vm, resolving_vm|
if vm.id
`VBoxManage guestproperty get #{vm.id} "/VirtualBox/GuestInfo/Net/1/V4/IP".split()[1]`
end
end
config.vm.define :puppet_server do |srv|
srv.vm.hostname = "puppet-server"
srv.vm.network :private_network, ip: '10.0.3.15'
srv.vm.provision "shell", inline: $puppetServerScript
srv.vm.synced_folder "src/puppet-server", "/etc/puppet", create: true
end
config.vm.define :bareOSdirector do |srv|
srv.vm.hostname = "bareOSdirector"
srv.vm.network :private_network, ip: '10.0.3.10'
srv.vm.provision "shell", inline: $puppetClientBareOSdir
end
config.vm.define :webserver do |srv|
srv.vm.hostname = "webserver"
srv.vm.network :private_network, ip: '10.0.3.8'
srv.vm.provision "shell", inline: $puppetClientWebserver
end
end
I thought it had something to do with the hosts file itself, so I emptied it and re-ran the command, but it still doesn't update it.

sh: 1: Syntax error: "(" unexpected turned out to be a shell error because the ruby split was contained in the shell command by accident.
There were 2 problems...
The syntax was a little bit wrong there was a ``` in the wrong spot between the shell and the ruby syntax.
I was getting the IP address of the wrong card...
I tried running the command to obtain the from the command line with:
VBoxManage guestproperty get "puppet_server" "/VirtualBox/GuestInfo/Net/1/V4/IP
Value: 172.x.x.x
and it yielded the wrong ip address...so instead I tried:
VBoxManage guestproperty get "puppet_server" "/VirtualBox/GuestInfo/Net/2/V4/IP
Value: 10.0.3.15
and I got the address I was expecting.
The block:
config.hostmanager.ip_resolver = proc do |vm, resolving_vm|
if vm.id
`VBoxManage guestproperty get #{vm.id} "/VirtualBox/GuestInfo/Net/1/V4/IP".split()[1]`
end
end
Should have been:
config.hostmanager.ip_resolver = proc do |vm, resolving_vm|
if vm.id
`VBoxManage guestproperty get #{vm.id} "/VirtualBox/GuestInfo/Net/2/V4/IP"`.split()[1]
end
end
Then after bringing all the machines up, I ran vagrant hostmanager again, and all the /etc/hosts files were filled in as expected.

Related

Vagrantfile - multible vm showing up with the same hostname

thanks for taking the time to look at my question.
I've created a Vagrantfile which launches two vm's, an ubuntu and a centos. I've stated in the Vagrantfile the hostname of both vm's but when I run vagrant up they both come up with the same hostname of centos90.
What am I doing wrong here.
Vagrant.configure("2") do |config|
config.vm.define "ub80" do |ub80|
ub80.vm.box = "hashicorp/precise32"
config.vm.hostname = "ubuntu80"
config.vm.network "private_network", ip: "192.168.33.80"
end
config.vm.define "cos90" do |cos90|
cos90.vm.box = "centos/7"
config.vm.hostname = "centos90"
config.vm.network "private_network", ip: "192.168.33.90"
end
me again!
syntax was wrong I was using config.vm.xxx for configurations instead of the name given in the config.vm.define command.
Below is the corect syntax:
Vagrant.configure("2") do |config|
config.vm.define "ub80" do |ub80|
ub80.vm.box = "hashicorp/precise32"
ub80.vm.hostname = "ubuntu80"
ub80.vm.network "private_network", ip: "192.168.33.80"
end
config.vm.define "cos90" do |cos90|
cos90.vm.box = "centos/7"
cos90.vm.hostname = "centos90"
cos90.vm.network "private_network", ip: "192.168.33.90"
end

Vagrantfile: syntax error, unexpected end-of-input, expecting keyword_end

I'm setting up a new Ansible controller and nodes on virtualbox with a Vargrantfile. I continue to get the error:
There is a syntax error in the following Vagrantfile. The syntax error
message is reproduced below for convenience:
/home/vagrant/ansible/Vagrantfile:19: syntax error, unexpected end-of-input, > expecting keyword_end
I'm changing the placement of the "end" keyword over and over, but still getting the same error on different lines. I'm sure this is simple and I'm just missing it, it's been one of those weeks...
Vagrant.configure("2") do |config|
config.vm.define "controller" do |controller|
controller.vm.box = "bento/ubuntu 16.04"
controller.vm.hostname = "controller"
controller.vm.network :private_network, ip: "10.10.10.10"
controller.vm.provider "virtualbox" do |vb|
vb.memory = "256"
end
end
(1..3).each do |i|
config.vm.define "node#{i}" do |node|
node.vm.box = "bento/ubuntu-16.04"
node.vm.hostname = "node#{i}"
node.vm.network :private_network, ip: "10.10.10.1#{i}"
node.vm.provider "virtualbox" do |vb|
vb.memory = "256"
end
end
I should be able to run vagrant up in the terminal and get an output of provisioning controllers/nodes in virtualbox. What am I missing?
You're missing 2 "end"s at the end of the file
Vagrant.configure("2") do |config|
config.vm.define "controller" do |controller|
controller.vm.box = "bento/ubuntu 16.04"
controller.vm.hostname = "controller"
controller.vm.network :private_network, ip: "10.10.10.10"
controller.vm.provider "virtualbox" do |vb|
vb.memory = "256"
end
end
(1..3).each do |i|
config.vm.define "node#{i}" do |node|
node.vm.box = "bento/ubuntu-16.04"
node.vm.hostname = "node#{i}"
node.vm.network :private_network, ip: "10.10.10.1#{i}"
node.vm.provider "virtualbox" do |vb|
vb.memory = "256"
end
end
end
end

Is it possible to execute a provisioner on a specific Vagrant machine after that machine's definition in the Vagrantfile has been ended?

I'd like to be able to spin up all of my Vagrant VMs for a project at once and then, at the very end, execute Ansible (using ansible_local) on one of those VMs. Is it possible to have a provisioner such as ansible_local run on a machine you've already previously defined?
Example of what I want to do:
# VM definitions
config.vm.define "control" do |control|
control.vm.hostname = "control.somedomain.local"
control.vm.network "private_network", ip: "172.28.128.3"
control.vm.provider "virtualbox" do |control_vbox|
control_vbox.name = "Ansible Controller"
control_vbox.cpus = 2
control_vbox.memory = 1024
end
end
config.vm.define "web01" do |web|
control.vm.hostname = "web01.somedomain.local"
control.vm.network "private_network", ip: "172.28.128.4"
control.vm.provider "virtualbox" do |web_vbox|
web_vbox.name = "Web Server 1"
web_vbox.cpus = 2
web_vbox.memory = 1024
end
end
# run ansible_local provisioner from the control VM
config.vm.provision "ansible_local" do |ansible|
ansible.run_on_vm = "control"
ansible.playbook = "some_playbook.yml"
end
You can make the following change in your Vagrantfile
# VM definitions
config.vm.define "control" do |control|
control.vm.hostname = "control.somedomain.local"
control.vm.network "private_network", ip: "172.28.128.3"
control.vm.provider "virtualbox" do |control_vbox|
control_vbox.name = "Ansible Controller"
control_vbox.cpus = 2
control_vbox.memory = 1024
end
# run ansible_local provisioner from the control VM
control.vm.provision "ansible_local" do |ansible|
ansible.run_on_vm = "control"
ansible.playbook = "some_playbook.yml"
end
end
config.vm.define "web01" do |web|
control.vm.hostname = "web01.somedomain.local"
control.vm.network "private_network", ip: "172.28.128.4"
control.vm.provider "virtualbox" do |web_vbox|
web_vbox.name = "Web Server 1"
web_vbox.cpus = 2
web_vbox.memory = 1024
end
end
so that the ansible provisioner will run only on the control VM
The other possibilities are
running the vagrant command in following order
$ vagrant up --no-provision // will spin up all the vms but will not provisiong
$ vagrant provision control // will provision the control vm
check the vagrant trigger plugin which can be used to run specific command, I have not tested though with multi machine environment

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.

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