lspci via facter

160 views
Skip to first unread message

Cam Mac

unread,
Jan 5, 2017, 6:27:36 AM1/5/17
to Puppet Users
Hi,

I'm trying to get videocard information into facter for installation of drivers. I've been able to
get to the point of getting it to work in ruby, but not in Puppet. One thing I need to do is
remove non-word characters, such as brackets, hash symbols, etc, as I run a grep command
in my Puppet manifest which doesn't work when certain special characters are present (apart from a comma).

This is what I have so far:

require 'facter'

Facter.add("videocard") do
  confine :kernel => :linux
  ENV["PATH"]="/bin:/sbin:/usr/bin:/usr/sbin"
  setcode do
  ctrl = []
  lspciexists = system "/bin/bash -c 'which lspci >&/dev/null'"
  if $?.exitstatus == 0
    output = %x{lspci}
    output.split("\n").each {|s|
    if s =~ /VGA\s+compatible\s+controller/
      s.gsub!(/(\W)/, " ").gsub!(/\s+/," ")
      ctrl << s
      end
    }
    end
    controllers.join(',')
  end
end

What am I doing wrong here?

Thanks for any help,

-Cam

Garrett Honeycutt

unread,
Jan 5, 2017, 8:59:42 PM1/5/17
to puppet...@googlegroups.com
Hi Cam,

I have not tested the above code, though you say it works in Ruby and
not Puppet, so guessing you have an issue with where the code is on disk
or missing some steps in the process.

Ensure that this code is in
$modulepath:/<module>/lib/facter/videocard.rb. You can remove the
'require facter' line. Then run the puppet agent so that pluginsync puts
the code in the right place. Now run `facter -p videocard` and you
should see your output.

Here's an example[1] of a module with a fact that is similar to what you
are doing. Notice it uses Facter::Util::Resolution.which instead of system.

Here's an example[2] of how to write unit tests for your new fact.

[1] -
https://github.com/ghoneycutt/puppet-module-ssh/blob/master/lib/facter/ssh.rb

[2] -
https://github.com/ghoneycutt/puppet-module-ssh/blob/master/spec/unit/facter/ssh_spec.rb

Best regards,
-g

--
Garrett Honeycutt
@learnpuppet
Puppet Training with LearnPuppet.com
Mobile: +1.206.414.8658

Cam Mac

unread,
Jan 6, 2017, 6:11:16 AM1/6/17
to Puppet Users
Hi Garrett,

During a Puppet run, I can see it modifying the local copy of the videocard.rb on the client, when I've modified it. It just doesn't set the fact.
I'll try Facter::Util::Resolution and see if that gets any better results.

Thanks,

Cam

Cam Mac

unread,
Jan 6, 2017, 7:42:33 AM1/6/17
to Puppet Users
Update: I can get it to return all of the output of lspci, but can't filter it for the string I'm looking for. Example:

  setcode do
    controllers = []
    if Facter::Util::Resolution.which('lspci')
      if Facter::Util::Resolution.which('grep')
        output = Facter::Util::Resolution.exec(%q{lspci|grep -iP "VGA\s+compatible\s+controller"})
        unless output.nil?
          output.gsub!(/(\W)/, " ").gsub!(/\s+/," ")
        end
      end
    end
.
.

I know the 'lspci|grep' works in the shell, but it doesn't in Ruby

If I do it to go through each line in the ouput, splitting on newlines, I get nothing (I've left off the search and replace for now):

  setcode do
    controllers = []
    if Facter::Util::Resolution.which('lspci')
      if Facter::Util::Resolution.which('grep')
        output = Facter::Util::Resolution.exec('lspci')
        output.split.each {|s|

          if s =~ /VGA\s+compatible\s+controller/
            controllers << s

          end
        }
       end
       controllers.join(',')
     end
   end




John Gelnaw

unread,
Jan 8, 2017, 1:08:09 PM1/8/17
to Puppet Users

I've been using the following code for a really long time now-- I think I 'borrowed' it from someone else.

# videocards.rb                                                                  
 
controllers
= []
output
= %x{lspci}
output
.each_line {|s|
    controllers
.push($1) if s =~ /VGA compatible controller: (.*)/
}
 
for vc in 0...controllers.length
    thecard
= "videocard" + vc.to_s
   
Facter.add(thecard) do
        setcode
do
            controllers
[vc]
       
end
   
end
end


Obviously it's only going to work if lspci is in the path when puppet runs.

Cam Mac

unread,
Jan 10, 2017, 9:00:44 AM1/10/17
to Puppet Users
Thanks John. That didn't work for me, not sure why, but this did:

require 'facter'

Facter.add("vgactrl") do

  confine :kernel => :linux
  ENV["PATH"]="/bin:/sbin:/usr/bin:/usr/sbin"
  setcode do
    controllers = []
    if Facter::Util::Resolution.which('lspci')
      output = Facter::Util::Resolution.exec('lspci')
      unless output.nil?
        output.split("\n").each do |line|
          if line =~ /VGA\s+compatible\s+controller/
            line.gsub!(/(\W)/, " ").gsub!(/\s+/," ")
            controllers << line
          end
        end

      end
    end
    controllers.join(',')
  end
end

I wonder if it is the version of Ruby I'm using? This is on EL7

Anyway, thanks for all the suggestions. I've decided that I don't need the actual string returned in the fact any more, but
I'll just set it to true or false in the facter script if it matches.

Cheers
Reply all
Reply to author
Forward
0 new messages