Search code examples
rubyperformancepuppetvagrantfacter

Puppet facter slow for some network facts


I'm learning about vagrant and puppet. When I use the vagrant lucid32 (Ubuntu 10.04), puppet seems very slow. I've fixed the fqdn problem (question 7780322) but it's still very slow.

I've traced (part of) the problem to facter. Asking for ipaddress is very quick, but ipaddress_eth0 takes 20 seconds:

root@a:/# time facter ipaddress
10.0.2.15

real    0m0.031s
user    0m0.024s
sys     0m0.004s
root@a:/# time facter ipaddress_eth0
10.0.2.15

real    0m20.126s
user    0m0.080s
sys     0m0.020s
root@a:/# 

Looking for ipaddress_lo is also slow.

Can anyone help me with a solution or a suggestion for how to debug this? I'm new to Ruby, but willing to learn.

Thanks.


Solution

  • Problem was that arp -a runs very slowly.

    vagrant@lucid32:~$ time arp -a
    ? (10.0.2.3) at 52:54:00:12:35:03 [ether] on eth0
    ? (10.0.2.2) at 52:54:00:12:35:02 [ether] on eth0
    
    real    0m20.022s
    user    0m0.004s
    sys     0m0.000s
    vagrant@lucid32:~$
    

    I assume that this is a problem with some combination of virtualbox (4.1.12_77245), host-only networking, ubuntu 10.04, and windows 7 host OS.

    As a workaround, assuming that I can learn a bit about puppet without it knowing my mac addresses, I replaced line 7 of /opt/ruby/lib/ruby/gems/1.8/gems/facter-1.6.0/lib/facter/arp.rb as follows:

    require 'facter/util/ip'
    
    Facter.add(:arp) do
      confine :kernel => :linux
      setcode do
        ### output = Facter::Util::Resolution.exec('arp -a') # disable for slow arp
        output = "" ### return a blank, rather than the real (but slow) arp
        if not output.nil?
          arp = ""
          output.each_line do |s|
            if s =~ /^\S+\s\S+\s\S+\s(\S+)\s\S+\s\S+\s\S+$/
              arp = $1.downcase
              break # stops on the first match
            end
          end
        end
        "fe:ff:ff:ff:ff:ff" == arp ? arp : nil
      end
    end
    
    Facter::Util::IP.get_interfaces.each do |interface|
      Facter.add("arp_" + Facter::Util::IP.alphafy(interface)) do
        confine :kernel => :linux
        setcode do
          arp = Facter::Util::IP.get_arp_value(interface)
          "fe:ff:ff:ff:ff:ff" == arp ? arp : nil
        end
      end
    end