4

I'd like my vagrantfile to automatically set CPU and RAM based on the host specs.

I found this snippet:

 config.vm.provider "virtualbox" do |v|
      host = RbConfig::CONFIG['host_os']
      # Give VM 1/4 system memory & access to all cpu cores on the host
      if host =~ /darwin/
        cpus = `sysctl -n hw.ncpu`.to_i
        # sysctl returns Bytes and we need to convert to MB
        mem = `sysctl -n hw.memsize`.to_i / 1024 / 1024 / 4
      elsif host =~ /linux/
        cpus = `nproc`.to_i
        # meminfo shows KB and we need to convert to MB
        mem = `grep 'MemTotal' /proc/meminfo | sed -e 's/MemTotal://' -e 's/ kB//'`.to_i / 1024 / 4
      else # sorry Windows folks, I can't help you
        cpus = 2
        mem = 1024
      end

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

It however doesn't do Windows (it sets default values 2 and 1024 instead).

Anyone got any clue how to do this?

Mentor
  • 965
  • 9
  • 21

3 Answers3

6

I managed to figure it our and integrated it into a Git repo.

The code:

cpus = `wmic cpu get NumberOfCores`.split("\n")[2].to_i
mem = `wmic OS get TotalVisibleMemorySize`.split("\n")[2].to_i / 1024 /4
Mentor
  • 965
  • 9
  • 21
3

To unify the above answers into a complete example, your vagrant file should contain this provisioning section:

Note the mem_ratio and cpu_exec_cap variables which you can use to tune how much of the hosts RAM and CPU cycles to allocate to the VM.

config.vm.provider "virtualbox" do |v|
  mem_ratio = 3/4
  cpu_exec_cap = 75
  host = RbConfig::CONFIG['host_os']
  # Give VM 3/4 system memory & access to all cpu cores on the host
  if host =~ /darwin/
    cpus = `sysctl -n hw.ncpu`.to_i
    # sysctl returns Bytes and we need to convert to MB
    mem = `sysctl -n hw.memsize`.to_i / 1024^2 * mem_ratio
  elsif host =~ /linux/
    cpus = `nproc`.to_i
    # meminfo shows KB and we need to convert to MB
    mem = `grep 'MemTotal' /proc/meminfo | sed -e 's/MemTotal://' -e 's/ kB//'`.to_i / 1024 * mem_ratio
  else # Windows folks
    cpus = `wmic cpu get NumberOfCores`.split("\n")[2].to_i
    mem = `wmic OS get TotalVisibleMemorySize`.split("\n")[2].to_i / 1024 * mem_ratio
  end

  puts "Provisioning VM with #{cpus} CPU's (at #{cpu_exec_cap}%) and #{mem/1024} GB RAM."

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

  v.customize ["modifyvm", :id, "--cpuexecutioncap", cpu_exec_cap]
end
Nick Breen
  • 359
  • 2
  • 9
  • On my system (Windows 10) the line ``mem = /`wmic OS get TotalVisibleMemorySize/`.split("\n")[2].to_i / 1024 * mem_ratio`` was evaluating to `0`, so I changed `mem_ratio = 3/4` to `mem_ratio = 0.75` and added `.round` to ``mem = (`wmic OS get TotalVisibleMemorySize`.split("\n")[2].to_i / 1024 * mem_ratio).round``. This now works on WIndows 10, but I'm not sure what affect it will have on other OS. – the-notable Dec 02 '18 at 22:00
1

It is there in the script you have downloaded :

sorry Windows folks, I can't help you

else # sorry Windows folks, I can't help you
    cpus = 2
    mem = 1024
  end

so you can change those default values but unfortunately windows does not provide easy to use commands to retrieve those informations

Now if you want to do it yourself, it should be possible, look at the wmic command, you can get a lot, and with little parsing you should have the necessary information - For example

C:\Users\fhenri>wmic os get freephysicalmemory
FreePhysicalMemory
1564244

C:\Users\fhenri>wmic.exe cpu get NumberOfCores
NumberOfCores
1

you could also look at systeminfo this is pretty verbose and locale specific so might be more difficult to parse

Frederic Henri
  • 51,761
  • 10
  • 113
  • 139