Hypervisor Drivers
Honestly, this is a topic I was hoping I wouldn't have to cover but it looks like I do.
"Work to add features in VirtualBox Guest Additions to the Linux kernel is underway by kernel developers. The first fruits of their labor will appear in Linux 4.16.
These additional features are licensed under the GPL and sit in the kernel tree. That means no additional proprietary code or binary blobs are loaded on your system.
Why does this matter?
Well, it means the next time you boot a Linux distribution with the Linux 4.16 (or later) kernel, VirtualBox Guest Additions will be already installed. You won’t need to enable, add, install or tweak anything (in theory).
Basic system integration features like seamless mode and copy and paste between guest and host will “just work”. Devs even plan to support shared folders out of the box in a future kernel release.
This is a huge win; it means more people will be able to cautiously sample Linux distros and get a better first impression of them. It will also make developers’ lives easier by allowing them to quickly test, deploy and iterate between multiple VMs without jumping through hoops for each and every one."
Unfortunately, after experimenting with Bionic Beaver in VirtualBox, I've come to the conclusion that support isn't quite there yet. Besides, what do you do if you are using a hypervisor other than VirtualBox, such as VMWare?
VirtualBox Guest Additions
When I'm developing, I run my VM in full screen mode and I often forget that I'm in a virtualized environment. The desktop experience is no different than if I was developing on a real machine. This only works, however, if you have Guest Additions installed. In short, not having Guest Additions installed is a deal breaker for me.
Installing Guest Additions
Packer, if you tell it to, will give you access to the Guest Additions files as the box is built. You just have to add the logic to mount the ISO and execute the necessary commands.
Make the Guest Additions ISO Available
"builders": [{
"type" : "virtualbox-ovf",
"source_path" : "{{user `virtualbox_appliance`}}",
"ssh_username": "{{user `ssh_name`}}",
"ssh_password": "{{user `ssh_pass`}}",
"boot_wait" : "30s",
"format" : "ova",
"guest_additions_mode" : "upload",
"guest_additions_path" : "VBoxGuestAdditions_{{.Version}}.iso",
"headless" : false,
"keep_registered" : false,
"shutdown_command" : "sudo shutdown --poweroff now",
"shutdown_timeout" : "2m",
"skip_export" : false,
"output_directory" : "output-virtualbox-ovf",
"vm_name" : "packer-bionic-xubuntu"
},
What we've done here is to tell Packer to make the ISO available to us in the home directory.
Install The Guest Additions
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"scripts" : ["scripts/install-hypervisor-tools.sh","scripts/prepare-for-compression.sh"]
}
Here, we are introducing a new script into the build pipeline that will manipulate the ISO and install the tools.
Installation Bash Script
#!/usr/bin/env bash
echo "PACKER_BUILD_NAME is ${PACKER_BUILD_NAME}"
echo "PACKER_BUILDER_TYPE is ${PACKER_BUILDER_TYPE}"
if [ "${PACKER_BUILDER_TYPE}" == "vmware-vmx" ]
then
echo "Installing VMWare Tools"
ISO=/home/vagrant/linux.iso
sudo mount -o loop ${ISO} /mnt
ls -alh /mnt
cp /mnt/VMwareTools-10.2.5-8068393.tar.gz /tmp
cd /tmp && tar zxvf VMwareTools-10.2.5-8068393.tar.gz && cd vmware-tools-distrib && sudo ./vmware-install.pl -d default
sudo umount /mnt
sudo rm -rf /home/vagrant/${ISO}
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get update
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get --yes install open-vm-tools open-vm-tools-desktop
else
echo "Installing VirtualBox Guest Additions"
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get update
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get --yes install gcc make perl
VBOX_VERSION=$(cat /home/vagrant/.vbox_version)
VBOX_ISO=VBoxGuestAdditions_$VBOX_VERSION.iso
sudo mount -o loop ${VBOX_ISO} /mnt
sudo /mnt/VBoxLinuxAdditions.run
sudo umount /mnt
sudo rm -rf /home/vagrant/${VBOX_ISO}
fi
In the script, you'll notice that we run different commands based on the value of the PACKER_BUILDER_TYPE
. This is because I have Packer build boxes for both VirtualBox and VMWare at the same time. Most people don't do that so your script will be simpler. The basic steps are:
- install necessary packages needed to install the Guest Additions
- mount the ISO
- run the script
- clean up
Conclusion
That is pretty much it. The trick is to learn how to run the installation tools in unattended mode. Be aware that as new versions of the tools come out, sometimes their dependencies change and you have to install different packages. The best way to troubleshoot that is to spin up a throwaway VM and install the tools by hand, noting what is broken and/or missing.
Full Packer File
{
"description": "Builds a Xubuntu 18.04 desktop box with various software development tools installed",
"min_packer_version": "1.2.3",
"variables": {
"ssh_name" : "vagrant",
"ssh_pass" : "vagrant",
"virtualbox_appliance": "bionic-beaver.ova",
"vmware_appliance" : "bionic-beaver.vmx",
"comment" : "Ubuntu 18.04 Bionic Beaver with VirtualBox and VMWare support. See [README](https://github.com/kurron/jvm-development-environment) for launch instructions.",
"cloud_user" : "{{env `VAGRANT_CLOUD_ACCOUNT`}}",
"cloud_token" : "{{env `VAGRANT_CLOUD_TOKEN`}}"
},
"builders": [{
"type" : "virtualbox-ovf",
"source_path" : "{{user `virtualbox_appliance`}}",
"ssh_username": "{{user `ssh_name`}}",
"ssh_password": "{{user `ssh_pass`}}",
"boot_wait" : "30s",
"format" : "ova",
"guest_additions_mode" : "upload",
"guest_additions_path" : "VBoxGuestAdditions_{{.Version}}.iso",
"headless" : false,
"keep_registered" : false,
"shutdown_command" : "sudo shutdown --poweroff now",
"shutdown_timeout" : "2m",
"skip_export" : false,
"output_directory" : "output-virtualbox-ovf",
"vm_name" : "packer-bionic-xubuntu"
},
{
"type" : "vmware-vmx",
"source_path" : "{{user `vmware_appliance`}}",
"ssh_username": "{{user `ssh_name`}}",
"ssh_password": "{{user `ssh_pass`}}",
"boot_wait" : "30s",
"disable_vnc" : true,
"headless" : false,
"output_directory" : "output-vmware-vmx",
"shutdown_command" : "sudo shutdown --poweroff now",
"shutdown_timeout" : "2m",
"skip_compaction" : false,
"tools_upload_flavor" : "linux",
"vm_name" : "packer-bionic-xubuntu"
}],
"provisioners": [
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"script" : "scripts/install-ansible.sh"
},
{
"type" : "ansible-local",
"playbook_file" : "ansible/playbook.yml",
"galaxy_file" : "ansible/requirements.yml",
"extra_arguments" : ["--verbose"]
},
{
"type" : "shell",
"environment_vars": ["DEBIAN_FRONTEND=noninteractive"],
"scripts" : ["scripts/install-hypervisor-tools.sh","scripts/prepare-for-compression.sh"]
}
],
"post-processors": [
[
{
"compression_level" : 9,
"keep_input_artifact": false,
"output" : "vagrant/xubuntu-bionic-{{.Provider}}.box",
"type" : "vagrant",
"vagrantfile_template": "vagrantfile.template"
},
{
"access_token" : "{{user `cloud_token`}}",
"box_tag" : "{{user `cloud_user`}}/bionic-xubuntu",
"type" : "vagrant-cloud",
"version" : "{{isotime \"2006.01.0215\"}}",
"version_description": "{{user `comment`}}"
}
]
]
}
Full scripts/install-hypervisor-tools.sh File
#!/usr/bin/env bash
echo "PACKER_BUILD_NAME is ${PACKER_BUILD_NAME}"
echo "PACKER_BUILDER_TYPE is ${PACKER_BUILDER_TYPE}"
echo "PACKER_HTTP_ADDR is ${PACKER_HTTP_ADDR}"
if [ "${PACKER_BUILDER_TYPE}" == "vmware-vmx" ]
then
echo "Installing VMWare Tools"
ISO=/home/vagrant/linux.iso
sudo mount -o loop ${ISO} /mnt
ls -alh /mnt
cp /mnt/VMwareTools-10.2.5-8068393.tar.gz /tmp
cd /tmp && tar zxvf VMwareTools-10.2.5-8068393.tar.gz && cd vmware-tools-distrib && sudo ./vmware-install.pl -d default
sudo umount /mnt
sudo rm -rf /home/vagrant/${ISO}
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get update
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get --yes install open-vm-tools open-vm-tools-desktop
else
echo "Installing VirtualBox Guest Additions"
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get update
until sudo apt-get --yes update; do echo "Waiting for apt lock"; sleep 5; done
sudo apt-get --yes install gcc make perl
VBOX_VERSION=$(cat /home/vagrant/.vbox_version)
VBOX_ISO=VBoxGuestAdditions_$VBOX_VERSION.iso
sudo mount -o loop ${VBOX_ISO} /mnt
sudo /mnt/VBoxLinuxAdditions.run
sudo umount /mnt
sudo rm -rf /home/vagrant/${VBOX_ISO}
fi