Creating virtual dev environment with xhyve

xhyve is the awesome lightweight virtual machine for Mac OS X.

In this post, I will show you how to have the same target as Vagrant with
xhyve. At the end of this post, we will have the virtual environment which
synced with the host OS’s folder to work on our project.

Our virtual environment will run Ubuntu Server
14.04
, which has built-in Python
support.

 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 the startup 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.

In this post, we have Python built-in with Ubuntu, and will run the simple HTTP server with:

python -m SimpleHTTPServer

 Synching shared folder from Host to Guest

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

 Setup NFS Server on Host

On Mac OS X, you have to create a file named **/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’s 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 an 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 stacks as you can without messing up your Host machine.

 
1
Kudos
 
1
Kudos

Now read this

Multiple binaries in a Rust project

If you have a project that needs to compile into multiple binaries or libraries, you can config it in Cargo.toml like this: ... [[lib]] name = "<your-lib-name>" src = "<path-to-source>" [[bin]] name =... Continue →

Subscribe to The Full Snack Developer

Don’t worry; we hate spam with a passion.
You can unsubscribe with one click.

S9LXLa7CrucYvIzThg7