In two of my very first blog posts, “Installing CentOS 6.2 with VirtualBox” and “Installing Gnome on Centos With Virtualbox”, I installed CentOS 6.2 using VirtualBox and later used that to create a basebox for Vagrant.
In this post I want to go back to the very first step of installing CentOS and automate it. Luckily there is a tool called VeeWee that does this and more.
While searching I also found a nice post on building Vagrant boxes with VeeWee.
Let’s start by installing VeeWee:
$ mkdir <some_where>/veewee_test
$ cd <some_where>/veewee_test
$ gem install veewee
$ vagrant basebox templates
The last command lists available templates. A template is a set of prepared configuration files so you don’t need to start from scratch. I wanted CentOS-6.2-x86_64-minimal. For CentOS 6.3 I would use the 6.2 templates and adjust them.
Before starting I created <some_where>/veewee_test/iso and put my ISO image in it (VeeWee would otherwise download it automatically).
Then I ran:
$ vagrant basebox define 'my_cool_basebox' 'CentOS-6.2-x86_64-minimal'
$ vagrant basebox build 'my_cool_basebox'
$ vagrant basebox validate 'my_cool_basebox'
$ vagrant basebox export 'my_cool_basebox'
$ vagrant box add 'my_cool_basebox' 'my_cool_basebox.box'
$ vagrant init 'my_cool_basebox'
$ vagrant up
$ vagrant ssh
Basically, that’s all you need. As always, things didn’t go as smoothly as expected. When running vagrant basebox validate my_cool_basebox, I got the following in the last validation step:
[validation output retained as-is]
Scenario: Checking shared folders # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:47
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password | keyfile |
| vagrant | vagrant | vagrant-private.key |
And I run "mount|grep veewee-validation" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
done!
Then I should see "veewee-validation" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
expected: /veewee-validation/
got: nil (using =~) (RSpec::Expectations::ExpectationNotMetError)
Failing Scenarios:
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:47 # Scenario: Checking shared folders
7 scenarios (1 failed, 6 passed)
21 steps (1 failed, 20 passed)
0m1.176s
Something went wrong. I continued the steps after validation just to see what would happen and got another error when doing vagrant up:
$ vagrant up
[default] Importing base box 'my_cool_basebox'...
[default] No guest additions were detected on the base box for this VM! Guest
additions are required for forwarded ports, shared folders, host only
networking, and more. If SSH fails on this machine, please install
the guest additions and repackage the box to continue.
This is not an error message; everything may continue to work properly,
in which case you may ignore this message.
[default] Matching MAC address for NAT networking...
[default] Clearing any previously set forwarded ports...
[default] Fixed port collision for 22 => 2222. Now on port 2200.
[default] Forwarding ports...
[default] -- 22 => 2200 (adapter 1)
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Mounting shared folders...
[default] -- v-root: /vagrant
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` v-root /vagrant
Logging into the box worked:
$ vagrant ssh
Last login: Tue Jul 24 21:21:33 2012 from 10.0.2.2
[vagrant@localhost ~]$
So it basically worked, but shared folders failed. The build output indicated a problem installing the guest additions:
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.32-220.el6.x86_64
Building the main Guest Additions module[FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions[ OK ]
Installing the Window System drivers[FAILED]
(Could not find the X.Org or XFree86 Window System.)
dd: writing to `/tmp/clean': No space left on device
15493137+0 records in
15493136+0 records out
7932485632 bytes (7.9 GB) copied, 56.7727 s, 140 MB/s
In postinstall.sh I found the entry that tried to install the exact package name, but it failed with:
No package kernel-devel-2.6.32-220.el6.x86_64 available.
I logged into the Vagrant box and tried to install manually; the package was not found. Checking an old blog post showed I had used yum install kernel-devel previously, which worked now:
$ yum info kernel-devel
Loaded plugins: fastestmirror, presto
Loading mirror speeds from cached hostfile
* base: ftp.belnet.be
* extras: ftp.belnet.be
* updates: mirror.nucleus.be
Available Packages
Name : kernel-devel
Arch : x86_64
Version : 2.6.32
Release : 279.2.1.el6
Size : 7.6 M
Repo : updates
Summary : Development package for building kernel modules to match the kernel
URL : http://www.kernel.org/
License : GPLv2
Description : This package provides kernel headers and makefiles sufficient to build modules
: against the kernel package.
I edited postinstall.sh to install kernel-devel instead of the full version string and ran vagrant basebox build 'my_cool_basebox' again, but got this error:
[error traceback retained]
$ vagrant basebox build 'my_cool_basebox'
Shutting down vm my_cool_basebox
Verifying the isofile CentOS-6.2-x86_64-minimal.iso is ok.
Removing step [1] snapshot as it is no more valid
/Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/com/implementer/ffi.rb:106:in `call_and_check': Error in API call to save_settings: 2159738882 (VirtualBox::Exceptions::InvalidVMStateException)
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/com/implementer/ffi.rb:80:in `call_vtbl_function'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/com/implementer/ffi.rb:61:in `call_function'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/com/abstract_interface.rb:145:in `call_function'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/com/abstract_interface.rb:62:in `save_settings'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/vm.rb:422:in `with_open_session'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/virtualbox-0.9.2/lib/virtualbox/snapshot.rb:180:in `destroy'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/session.rb:836:in `transaction'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/session.rb:833:in `each'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/session.rb:833:in `transaction'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/session.rb:267:in `build'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/command/basebox_build.rb:28:in `execute'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/command/basebox.rb:36:in `execute'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/vagrant-1.0.3/lib/vagrant/cli.rb:42:in `execute'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/vagrant-1.0.3/lib/vagrant/environment.rb:167:in `cli'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/vagrant-1.0.3/bin/vagrant:43
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/bin/vagrant:19:in `load'
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/bin/vagrant:19
from /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/bin/ruby_noexec_wrapper:14
muntwissm15146:veewee_test twiss1$ vagrant destroy
[default] VM not created. Moving on...
I had to manually delete the VM and related files using the VirtualBox GUI and then tried vagrant basebox build 'my_cool_basebox' again.
During the build I peeked at the console and saw:
---> Package kernel-devel.x86_64 0:2.6.32-279.2.1.el6 will be installed
So kernel-devel was being installed, but later the guest additions build failed with the familiar message:
Uncompressing VirtualBox 4.1.12 Guest Additions for Linux.........
VirtualBox Guest Additions installer
Removing existing VirtualBox DKMS kernel modules[ OK ]
Removing existing VirtualBox non-DKMS kernel modules[ OK ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-2.6.32-220.el6.x86_64
Building the main Guest Additions module[FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions[ OK ]
Installing the Window System drivers[FAILED]
(Could not find the X.Org or XFree86 Window System.)
dd: writing to `/tmp/clean': No space left on device
15470233+0 records in
15470232+0 records out
7920758784 bytes (7.9 GB) copied, 47.686 s, 166 MB/s
I looked at /var/log/vboxadd-install.log inside the box:
/tmp/vbox.0/Makefile.include.header:97: *** Error: unable to find the sources of your current Linux kernel. Specify KERN_DIR=<directory> and run Make again. Stop.
Creating user for the Guest Additions.
Creating udev rule for the Guest Additions kernel module.
Then I checked versions:
$ yum list | grep kernel-devel
kernel-devel.x86_64 2.6.32-279.2.1.el6 updates
$ uname -r
2.6.32-220.el6.x86_64
The kernel version (uname -r) and the installed kernel-devel version didn’t match. I removed everything again:
$ vagrant destroy
$ vagrant box remove 'my_cool_basebox'
$ vagrant basebox destroy 'my_cool_basebox'
I reverted my changes in postinstall.sh and made one change in ks.cfg as described on this page: add /usr/bin/yum -y install kernel.
This time the build showed:
---> Package openssl-devel.x86_64 0:1.0.0-20.el6_2.5 will be installed
And installing the Guest Additions mostly succeeded:
Uncompressing VirtualBox 4.1.12 Guest Additions for Linux.........
VirtualBox Guest Additions installer
Removing existing VirtualBox DKMS kernel modules[ OK ]
Removing existing VirtualBox non-DKMS kernel modules[ OK ]
Building the VirtualBox Guest Additions kernel modules
Building the main Guest Additions module[ OK ]
Building the shared folder support module[ OK ]
Building the OpenGL support module[FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions[ OK ]
Installing the Window System drivers[FAILED]
(Could not find the X.Org or XFree86 Window System.)
Validating the box took longer and returned many errors:
[validation output retained as-is]
$ vagrant basebox validate my_cool_basebox
Feature: vagrant box validation
As a valid vagrant box
I need to comply to a set of rules
Scenario: Checking login # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:5
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password |
| vagrant | vagrant |
And I run "whoami" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "vagrant" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Scenario: Checking sudo # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:12
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password |
| vagrant | vagrant |
And I run "sudo whoami" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "root" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Scenario: Checking ruby # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:19
.undefined method `open_channel' for nil:NilClass (NoMethodError) When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password |
| vagrant | vagrant |
And I run ". /etc/profile ;ruby --version 2> /dev/null 1> /dev/null; echo $?" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "0" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Scenario: Checking gem # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:26
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password |
| vagrant | vagrant |
And I run ". /etc/profile; gem --version 2> /dev/null 1> /dev/null ; echo $?" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "0" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Scenario: Checking chef # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:33
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password |
| vagrant | vagrant |
And I run ". /etc/profile ;chef-client --version 2> /dev/null 1>/dev/null; echo $?" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "0" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Scenario: Checking puppet # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:40
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password |
| vagrant | vagrant |
And I run ". /etc/profile ; puppet --version 2> /dev/null 1>/dev/null; echo $?" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "0" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Scenario: Checking shared folders # /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:47
. When I ssh to "127.0.0.1" with the following credentials: # veewee-0.2.3/validation/features/steps/ssh_steps.rb:56
| username | password | keyfile |
| vagrant | vagrant | vagrant-private.key |
And I run "mount|grep veewee-validation" # veewee-0.2.3/validation/features/steps/ssh_steps.rb:98
undefined method `open_channel' for nil:NilClass (NoMethodError)
Then I should see "veewee-validation" in the output # veewee-0.2.3/validation/features/steps/ssh_steps.rb:167
Failing Scenarios:
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:5 # Scenario: Checking login
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:12 # Scenario: Checking sudo
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:19 # Scenario: Checking ruby
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:26 # Scenario: Checking gem
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:33 # Scenario: Checking chef
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:40 # Scenario: Checking puppet
cucumber /Users/twiss1/.rvm/gems/ruby-1.8.7-p358/gems/veewee-0.2.3/lib/veewee/../../validation/vagrant.feature:47 # Scenario: Checking shared folders
7 scenarios (7 failed)
21 steps (7 failed, 7 skipped, 7 passed)
9m20.915s
Interestingly, the VM console in the GUI was black and unresponsive. After resetting the VM via the VirtualBox GUI, validation succeeded:
7 scenarios (7 passed)
21 steps (21 passed)
0m1.015s
I exported the box. After vagrant up the same shared folder error appeared:
$ vagrant init 'my_cool_basebox'
`Vagrantfile` already exists in this directory. Remove it before
running `vagrant init`.
muntwissm15146:veewee_test twiss1$ vagrant up
[default] Importing base box 'my_cool_basebox'...
[default] No guest additions were detected on the base box for this VM! Guest
additions are required for forwarded ports, shared folders, host only
networking, and more. If SSH fails on this machine, please install
the guest additions and repackage the box to continue.
This is not an error message; everything may continue to work properly,
in which case you may ignore this message.
[default] Matching MAC address for NAT networking...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Mounting shared folders...
[default] -- v-root: /vagrant
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` v-root /vagrant
This didn’t make sense. I checked the earlier export step:
$ vagrant basebox export 'my_cool_basebox'
Vagrant requires the box to be shutdown, before it can export
Sudo also needs to work for user vagrant
Performing a clean shutdown now.
Executing command: sudo /sbin/halt -h -p
........
Machine my_cool_basebox is powered off cleanly
box my_cool_basebox.box already exists
Aha— it didn’t export a new box because the file already existed. I removed everything and checked the directory:
$ vagrant halt
$ vagrant destroy
$ vagrant box remove my_cool_basebox
$ vagrant basebox destroy my_cool_basebox
$ ls -al
Output:
total 1006480
drwxr-xr-x 8 twiss1 461641192 272 Jul 25 10:07 .
drwxr-xr-x 10 twiss1 461641192 340 Jul 24 17:27 ..
-rw-r--r--@ 1 twiss1 461641192 6148 Jul 24 17:30 .DS_Store
-rw-r--r-- 1 twiss1 461641192 14 Jul 24 17:28 .rvmrc
-rw-r--r-- 1 twiss1 461641192 3990 Jul 24 21:26 Vagrantfile
drwxr-xr-x 3 twiss1 461641192 102 Jul 24 18:05 definitions
drwxr-xr-x 4 twiss1 461641192 136 Jul 24 17:30 iso
-rw-r--r-- 1 twiss1 461641192 515301376 Jul 24 21:24 my_cool_basebox.box
So I had been working with an old box file the whole time. To fix that:
$ rm my_cool_basebox.box
$ vagrant basebox build 'my_cool_basebox'
Validation again produced many errors and the VirtualBox GUI console was black. Resetting the VM again fixed it, and after that everything went smoothly: validation, export, and starting the box.
$ vagrant box add 'my_cool_basebox' 'my_cool_basebox.box'
[vagrant] Downloading with Vagrant::Downloaders::File...
[vagrant] Copying box to temporary location...
[vagrant] Extracting box...
[vagrant] Verifying box...
[vagrant] Cleaning up downloaded box...
muntwissm15146:veewee_test twiss1$ vagrant up
[default] Importing base box 'my_cool_basebox'...
[default] Matching MAC address for NAT networking...
[default] Clearing any previously set forwarded ports...
[default] Forwarding ports...
[default] -- 22 => 2222 (adapter 1)
[default] Creating shared folders metadata...
[default] Clearing any previously set network interfaces...
[default] Booting VM...
[default] Waiting for VM to boot. This can take a few minutes.
[default] VM booted and ready for use!
[default] Mounting shared folders...
[default] -- v-root: /vagrant
Logging in:
$ vagrant ssh
Last login: Wed Jul 25 09:07:03 2012 from 10.0.2.2
Finally!
But I still have some open questions:
- How do I remove or delete everything completely if I want to start the whole procedure again?
- Why is the VirtualBox console sometimes black and validation then fails?
Done for today!