Dynamic Memory Allocation in Vagrant Virtual Machines on Windows Hosts

Whenever there is a constraint on the number of developers in a pool, it can make it more difficult to solve issues. As we have been developing Nittany-Vagrant, I have found that there is definitely a smaller pool of developers running on a Microsoft Windows host for their vagrant based virtual machines.

The extra credit problem of the day for me was how to allow vagrant to automatically size a virtual machine's memory pool when utilizing VirtualBox as the VM provider on Windows. This is a well known solution on OSX:

`sysctl -n hw.memsize`.to_i / 1024 / 1024 / 4

However, it took a bit of digging to figure out a way that could be reliably reproduced for the folks that are using our Nittany-Vagrant tool on Windows hosts.

Standard with Microsoft Windows is a command line interface to the Windows Management Interface (WMI) called WMIC. WMIC has a component that allows you to read/edit system information. In particular:

wmic os get TotalVisibleMemorySize

will pull the total memory that is available to Windows. However, this also produces a number of headers that we don't want. We can then use grep to pull a line that starts with digits:

grep '^[0-9]'

Use Ruby to cast it as an int (just to be sure):

.to_i

and then divide it by 1024 (to get MB instead of KB).

We then only want to use 1/4 of the RAM, so we divide it by 4 and slap it into the vm memory size customization:

v.customize ["modifyvm", :id, "--memory", mem]

That's it! That's all... but there were a few other catches that made this ... less intuitive than one would hope.

  1. grep doesn't exist on Windows systems. However, if you install git-scm for windows, it installs a number of GNU like tools including ssh and grep. If you ensure that these (located in "C:\Program Files (x86)\Git\bin") are on your path, you get grep. The easiest way to make sure this happens is to select the third option "Use GIT and optional Unix tools from the Windows Command Prompt" when installing git-scm. Winner.
  2. determining your host...
    RbConfig::CONFIG['host_os']
  3. will report what your host operating system is... kind of ... With git-scm installed, it reports as "mingw32". With this, you can specify the command to run to retrieve the memory size based upon what OS is being reported. This is more trial and error than it probably should be, however, it does work. If necessary, use:
    puts RbConfig::CONFIG['host_os']
    to be able to determine what your OS is reporting so you can branch appropriately in your Vagrantfile.

This leaves us with:

if host =~ /mingw32/
	      mem = `wmic os get TotalVisibleMemorySize | grep '^[0-9]'`.to_i / 1024 / 4
	      if mem < 1024
	        mem = 1024
	      end
end
v.customize ["modifyvm", :id, "--memory", mem]

Hopefully, that helps some independent windows based developer out there... Cheers, +A

Header image - Vagrant - courtesy of mike krzeszak Creative Commons 2.0