» Plugin Development: Guests

This page documents how to add new guest OS detection to Vagrant, allowingVagrant to properly configure new operating systems.Prior to reading this, you should be familiarwith the plugin development basics.

Warning: Advanced Topic! Developing plugins is anadvanced topic that only experienced Vagrant users who are reasonablycomfortable with Ruby should approach.

Vagrant has many features that requires doing guest OS-specificactions, such as mounting folders, configuring networks, etc. Thesetasks vary from operating system to operating system. If you find thatone of these does not work for your operating system, then maybe theguest implementation is incomplete or incorrect.

» Definition Component

Within the context of a plugin definition, new guests can be definedlike so:

  1. guest "ubuntu" do
  2. require_relative "guest"
  3. Guest
  4. end

Guests are defined with the guest method. The first argument is thename of the guest. This name is not actually used anywhere, but may in thefuture, so choose something helpful. Then, the block argument returns aclass that implements the Vagrant.plugin(2, :guest) interface.

» Implementation

Implementations of guests subclass Vagrant.plugin("2", "guest"). Withinthis implementation, only the detect? method needs to be implemented.

The detect? method is called by Vagrant at some point after the machineis booted in order to determine what operating system the guest is running.If you detect that it is your operating system, return true from detect?.Otherwise, return false.

Communication channels to the machine are guaranteed to be running at thispoint, so the most common way to detect the operating system is to dosome basic testing:

  1. class MyGuest < Vagrant.plugin("2", "guest")
  2. def detect?(machine)
  3. machine.communicate.test("cat /etc/myos-release")
  4. end
  5. end

After detecting an OS, that OS is used for variousguest capabilities that may berequired.

» Guest Inheritance

Vagrant also supports a form of inheritance for guests, since sometimesoperating systems stem from a common root. A good example of this is Linuxis the root of Debian, which further is the root of Ubuntu in many cases.Inheritance allows guests to share a lot of common behavior while allowingdistro-specific overrides.

Inheritance is not done via standard Ruby class inheritance because Vagrantuses a custom capability-based system.Vagrant handles inheritance dispatch for you.

To subclass another guest, specify that guest's name as a second parameterin the guest definition:

  1. guest "ubuntu", "debian" do
  2. require_relative "guest"
  3. Guest
  4. end

With the above component, the "ubuntu" guest inherits from "debian." Whena capability is looked up for "ubuntu", all capabilities from "debian" arealso available, and any capabilities in "ubuntu" override parent capabilities.

When detecting operating systems with detect?, Vagrant always does adepth-first search by searching the children operating systems beforechecking their parents. Therefore, it is guaranteed in the above examplethat the detect? method on "ubuntu" will be called before "debian."