Last Updated: May 05, 2016
·
3.244K
· huytd

Virtual develop environment with xhyve

Install Ubuntu on xhyve

Prepare the kernel and initrd

Because xhyve does not support BIOS or EFI booter. We need to pass the kernel and ramdisk file to xhyve manually.

Since OS X does not recognize the file system of Ubuntu ISO. We need a little hack to mount it.

Create a cloned ISO file named /tmp/tmp.iso of Ubuntu ISO disk.

$ dd if=/dev/zero bs=2k count=1 of=/tmp/tmp.iso
$ dd if=ubuntu.iso bs=2k skip=1 >> /tmp/tmp.iso

Now we can mount the ISO file to copy the necessary files:

$ hdiutil attach /tmp/tmp.iso

The ISO file now mounted at "Ubuntu-Server 14" volume.

$ cp /Volumes/Ubuntu-Server\ 14/install/vmlinuz .
$ cp /Volumes/Ubuntu-Server\ 14/install/initrd.gz .

Create virtual hard disk image

Create a virtual hard disk image so you can install your Linux distro on it. In this post, we create a 3GB disk named hdd.img

$ dd if=/dev/zero of=hdd.img bs=1g count=3

Create start up script for Ubuntu installation

Now, we create a new bash script to init and start up a virtual machine with xhyve, that use our hdd.img as a virtual hard disk and ubuntu.iso as a virtual CD. Then install Ubuntu to the virtual hard disk.

up.sh

#!/bin/sh

KERNEL="vmlinuz"
INITRD="initrd.gz"
CMDLINE="earlyprintk=serial console=ttyS0 acpi=off"

MEM="-m 1G"
NET="-s 2:0,virtio-net"
IMG_CD="-s 3,ahci-cd,ubuntu.iso"
IMG_HDD="-s 4,virtio-blk,hdd.img"
PCI_DEV="-s 0:0,hostbridge -s 31,lpc"
LPC_DEV="-l com1,stdio"

xhyve $MEM $PCI_DEV $LPC_DEV $NET $IMG_CD $IMG_HDD -f kexec,$KERNEL,$INITRD,"$CMDLINE"

Don't forget to chmod the script file, so you can execute it:

$ chmod +x up.sh

Start your virtual machine and install Ubuntu in text mode installer:

$ sudo ./up.sh

You have to run with sudo because virtio-net required root permission.

At the very end of the installation, don't forget to choose "Install the GRUB boot loader to the master boot record"

When you reach "Installation complete" screen, select "Go back" and choose "Execute a shell" to config copy installed kernel and initrd to Mac. Enter this to VM:

$ cd /target
$ sbin/ifconfig
$ tar c boot | nc -l -p 1234

Then back to Mac, enter this:

$ nc [IP] 1234 | tar x

As [IP] is the IP address you saw in VM ifconfig command.

Now, exit shell mode in VM

$ exit

And select "Finish the installation" to finishing up your Ubuntu Guest.

The Linux kernel from your virtual disk has been copied to your Mac's boot folder.

Modify start up script to boot Ubuntu from virtual hard disk

Now, modify the up.sh script to make it boot from installed Ubuntu in virtual hard disk instead of CD image.

up.sh

#!/bin/sh

KERNEL="boot/vmlinuz-3.16.0-30-generic"
INITRD="boot/initrd.img-3.16.0-30-generic"
CMDLINE="earlyprintk=serial console=ttyS0 acpi=off root=/dev/vda1 ro"

MEM="-m 1G"
NET="-s 2:0,virtio-net"
IMG_HDD="-s 4,virtio-blk,hdd.img"
PCI_DEV="-s 0:0,hostbridge -s 31,lpc"
LPC_DEV="-l com1,stdio"

xhyve $MEM $PCI_DEV $LPC_DEV $NET $IMG_HDD -f kexec,$KERNEL$INITRD,"$CMDLINE"

Now, start your virtual machine with:

$ sudo ./up

To shutdown the VM and go back to Mac terminal, enter:

$ sudo halt

Now your virtual machine is ready! Time to go to next step: Setting up develop environment.

Our target is to build something like Vagrant, which allow you create a virtual environment that linked to the folder on Host. So we can do anything with that virtual environment without damaging Host machine.

Setup dev environment on your Ubuntu Guest

It depends on which development environment you want to setup, maybe you want to install LAMP, or MEAN, or Ruby on Rails.

Synching shared folder from Host to Guest

To share a folder from host OS to guest OS, you have to setup NFS server on host and mount it in guest OS.

Setup NFS Server on Host

On Mac OS X, you have to create file /etc/exports to config which folder you want to share via NFS Server.

$ sudo touch /etc/exports

Then put the shared folder path in that file with the following syntax:

<Folder path>       -mapall=501

Don't forget to use sudo when editing your exports config:

$ sudo vi /etc/exports

Folder path is the full path to your shared folder. Mapall parameter tell NFS Server that which user has permission to access that folder. In this case, 501 is your current (and default) user ID.

To see your user ID, enter:

$ id

Example /etc/exports file:

/Users/huy/Shared       -mapall=501

Now, run the NFS Server with the following command:

$ sudo nfsd enable

If you already have NFS Server started up, you will want to restart it to make the new config available:

$ sudo nfsd restart

Now, you have your folder shared and will be visible with the Guest OS.

To check if it is available or not, run this command:

$ showmount -e

This will list all exported (shared) folder you have configured on Host.

Mount the folder on Guest

Before mounting NFS server on Guest OS, we have to install a NFS client package first.

Run this command on Guest:

$ sudo apt-get install rpcbind nfs-commond

Now you will be able to mount any folder from NFS Server (Host) by enter the following command:

$ sudo mount -o nolock -t nfs <host-ip>:/<folder-path> <target-parth>

For example, this command will mount /Users/huy/Shared folder from host, which has IP 192.168.64.1 to ~/Shared folder in Guest OS.

$ sudo mount -o nolock -t nfs 192.168.64.1:/Users/huy/Shared ~/Shared

Now, you have your virtual machine linked with a real folder on your Mac host.

In the next section, we will see how to use this develop environment in your real life projects.

Using virtual dev environment

In this section, we will use our dev environment to run a simple HTTP server with Python to serve a simple web page.

Prepare the dev folder on host

On host machine, create a project folder, let's say:

/Users/huy/Code/helloPy/

Export this to /etc/exports file:

$ sudo vi /etc/exports

/etc/exports
... /Users/huy/Code/helloPy/ -mapalls=501

And restart the NFS Server:

$ sudo nfsd restart

Mount and run HTTP server on Guest

On Guest VM, mount the project folder to somewhere, with the following command:

$ sudo mount -o nolock -t nfs 192.168.64.1:/Users/huy/Code/helloPy/ ~/Code/helloPy

Then, move to that folder and run the HTTP server:

$ cd ~/Code/helloPy
$ python -m SimpleHTTPServer

The server will run at port 8000 on Guest OS.

To get Guest's IP, run this command:

$ ifconfig

For example, the Guest VM has IP: 192.168.64.2

We can access the web server from Host machine by entering this address: http://192.168.64.2:8000/

Coding from Host and sync to Guest's HTTP server

You can use your favorite editor (such as Sublime, Atom, WebStorm,...) and modify the code, then refresh the web page you can see the result.

That's how we use it!

From now, you can create as much server as you want, running as many stack as you can without messing up your Host machine.