Skip to main content

Creating Virtual Images with VeeWee

·13 mins

In two of my very first blog posts, here and here, I have installed CentOS 6.2 using VirtualBox and later on have used that to create a basebox for Vagrant.

In this post, I would like to go back to the very first step of installing CentOS and automate this as well. Luckily there is a tool called VeeWee that serves this purpose and does even more.

While googling around I have also found a nice post on building vagrant boxes with VeeWee.

Let’s start by installing VeeWee:

{% highlight none %} $ mkdir <some_where>/veewee_test $ cd <some_where>/veewee_test $ gem install veewee $ vagrant basebox templates {% endhighlight %}

The last command will give you a long list of available templates. A template is a set of configuration files that have already been prepared so you don’t need to start from scratch. What I want is CentOS-6.2-x86_64-minimal. Perfect. For the newer 6.3 version of CentOS, I would take the 6.2 templates and change them accordingly.

Before I did anything, I have created the directory <some_where>/veewee_test/iso and put my ISO-image in it that I have already downloaded some time ago. Without that image in the predefined directory, VeeWee would automatically download it.

So we run:

{% highlight none %} $ 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 {% endhighlight %}

Basically, this is all you need. As always, things did not work as smooth as expected. When running vagrant basebox validate my_cool_basebox, I got the following message in the last validation step:

{% highlight none %} 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 {% endhighlight %}

Something went wrong apparently. Anyways, I did all the steps after the validation just to see what happens and got another error when doing vagrant up.

{% highlight none %} $ 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 {% endhighlight %}

Logging into the box was no problem though.

{% highlight none %} $ vagrant ssh Last login: Tue Jul 24 21:21:33 2012 from 10.0.2.2 [vagrant@localhost ~]$ {% endhighlight %}

Okay, basically it works, but we have some brownfields here. You never know the side effects, so it is always better to resolve it immediately. Checking the output from building the box clearly indicated that something went wrong while installing the guest additions.

{% highlight none %} 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 {% endhighlight %}

While checking postinstall.sh I have found the entry where it will install that package, but it went wrong while executing that command:

{% highlight none %} No package kernel-devel-2.6.32-220.el6.x86_64 available. {% endhighlight %}

To make sure, I have logged into my vagrant box and tried to install them manually, with the same result, it could not find the package. I have checked my old blog post what I did at that time. It was a simple yum install kernel-devel, this also worked in the new box with the following details:

{% highlight none %} $ 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. {% endhighlight %}

Then I have edited postinstall.sh to only use kernel-devel instead of kernel-devel-2.6.32-220.el6.x86_64 and ran vagrant basebox build 'my_cool_basebox' again, but got this:

{% highlight none %} $ 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… {% endhighlight %}

Somehow, I manually had to delete the virtual image and all related files using the VirtualBox-GUI and again tried vagrant basebox build 'my_cool_basebox'.

During the built of the box I took a peek at the console output, there it was:

{% highlight none %} —> Package kernel-devel.x86_64 0:2.6.32-279.2.1.el6 will be installed {% endhighlight %}

Fine so far, but then again:

{% highlight none %} 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 {% endhighlight %}

Shoot! Let’s look in that log file /var/log/vboxadd-install.log in the box, should have done that in the first place.

{% highlight none %} /tmp/vbox.0/Makefile.include.header:97: *** Error: unable to find the sources of your current Linux kernel. Specify KERN_DIR= and run Make again. Stop. Creating user for the Guest Additions. Creating udev rule for the Guest Additions kernel module. {% endhighlight %}

Then ran some commands to check on the exact version numbers.

{% highlight none %} $ yum list | grep kernel-devel kernel-devel.x86_64 2.6.32-279.2.1.el6 updates {% endhighlight %}

{% highlight none %} $ uname -r 2.6.32-220.el6.x86_64 {% endhighlight %}

Okay, removed everything again:

{% highlight none %} $ vagrant destroy $ vagrant box remove ‘my_cool_basebox’ $ vagrant basebox destroy ‘my_cool_basebox’ {% endhighlight %}

Reverted my changes in postintall.sh and made one change in ks.cfg as described on this page (add /usr/bin/yum -y install kernel).

Interesting, this time when running the build, I got

{% highlight none %} —> Package openssl-devel.x86_64 0:1.0.0-20.el6_2.5 will be installed {% endhighlight %}

Also, when installing the VirtualBox Guest Additions everything went fine:

{% highlight none %} 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.) {% endhighlight %}

Validating the box took longer as before and returned many errors:

{% highlight none %} $ 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 {% endhighlight %}

Interestingly, when I have tried to log into the box in the GUI, the screen was just black and did not respond.

After resetting the box via the VirtualBox-GUI everything was fine again and validation succeeded with:

{% highlight none %} 7 scenarios (7 passed) 21 steps (21 passed) 0m1.015s {% endhighlight %}

Then I have exported the box. After vagrant up the same story as before:

{% highlight none %} $ 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 {% endhighlight %}

This just can’t be, right?

Then, I have checked the console output from before and found:

{% highlight none %} $ 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 {% endhighlight %}

Aha, so it did not export a new box and I was still working with the old one. So I did:

{% highlight none %} $ vagrant halt $ vagrant destroy $ vagrant box remove my_cool_basebox $ vagrant basebox destroy my_cool_basebox $ ls -al {% endhighlight %}

And I got the following:

{% highlight none %} 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 {% endhighlight %}

So the whole time I was working on an old box. But why has it not been removed? If you know the answer, feel free to add it to the comments below.

{% highlight none %} $ rm my_cool_basebox.box $ vagrant basebox build ‘my_cool_basebox’ {% endhighlight %}

Again, the same thing, validation took long and produced many errors. The VirtualBox-GUI showed a black console screen and did not react. Resetting it, did the trick again.

After that, everything went smooth, from validation, over exporting to firing up the box.

{% highlight none %} $ 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 {% endhighlight %}

Logging in:

{% highlight none %} $ vagrant ssh Last login: Wed Jul 25 09:07:03 2012 from 10.0.2.2 {% endhighlight %}

Finally!

But there are some open questions that I have:

  1. How do I remove or delete everything completely if I want to start the whole procedure again?
  2. Why is the VirtualBox console screen black sometimes and the validation fails?

You know the answer? Again: Feel free to provide it in the comments below.

Done for today!