Puppet: System Administration Automated

Support

Virtual Machine Fact

Is a client running in a virtual machine?

Here is a fact that will detect a virtual guest and return the host. It will check if the host is running under Xen, VMware, Vserver or OpenVZ.

This fact has been tested on Debian, Fedora and CentOS.

For Xen, it will detect whether you are a xen dom0 or a xen domU (reports xen0 and xenu respectively). It's also worth pointing out that a xenU can have an independent wall clock (i.e., separate to the xen0 clock) if 1 is poked into /proc/sys/xen/independent_wallclock. I don't really see the point in this, as you should just make sure your xen dom0 has the correct time.

Fact

Facter.add("virtual") do
  confine :kernel => :linux
  
  ENV["PATH"]="/bin:/sbin:/usr/bin:/usr/sbin"
  
  result = "physical"
  
  setcode do
    
    if FileTest.exists?("/proc/user_beancounters")
      result = "openvz"
    end

    # lspci exists on openvz but fails, so it must be checked first and this check must not be run on openvz
    if result == "physical"
      lspciexists = system "which lspci >&/dev/null"
      if $?.exitstatus == 0
        output = %x{lspci}
        output.each {|p|
          # --- look for the vmware video card to determine if it is virtual =>
vmware.
          # ---     00:0f.0 VGA compatible controller: VMware Inc [VMware SVGA II] PCI Display Adapter
          result = "vmware" if p =~ /VMware/
        }
      end
    end

    # VMware server 1.0.3 rpm places vmware-vmx in this place, other versions or platforms may not.
    if FileTest.exists?("/usr/lib/vmware/bin/vmware-vmx")
      result = "vmware_server"
    end

    if FileTest.exists?("/proc/sys/xen/independent_wallclock")
      result = "xenu"
    elsif FileTest.exists?("/proc/xen/capabilities")
      txt = File.read("/proc/xen/capabilities")
      if txt =~ /control_d/i
        result = "xen0"
      end
    end

    mountexists = system "which mount >&/dev/null"
    if $?.exitstatus == 0
      output = %x{mount}
      output.each {|p|
        result = "vserver" if p =~ /\/dev\/hdv1/
      }
    end

    result
  end
end

See also Recipes/VMWareGuest for more information about using the $productname fact for vmware, which is possibly cleaner for other virtual machines.

Puppet

class ntpd {

  $ntp_package = $operatingsystem ? {
                    debian  => "ntp-server",
                    default => "ntp"
                 }
                    
  package { $ntp_package: 
               ensure   => installed,
          }
  
  service { ntpd: 
             ensure   => $virtual ? {
                            openvz  => stopped,
                            vmware  => stopped,
                            xenu    => stopped,
                            vserver => stopped,
                            default => running
                         },
             enable   => $virtual ? {
                            openvz  => false,
                            vmware  => false,
                            xenu    => false,
                            vserver => false,
                            default => true
                         },
             require  => Package[$ntp_package]
          }
}

This puppet recipe enables or disables the ntp daemon, cause VMware guests don't like it.

Note: To keep VMware guest clocks in time install VMware-tools and add "tools.syncTime = "TRUE"" to the vm config. This doesn't appear to work particularly well but it is what VMware recommend.