Skip to content

Commit

Permalink
ipmitool_fru: Add new fact to show to information from ipmtool fru
Browse files Browse the repository at this point in the history
This CR adds a new structured fact called ipmitool with two keys fru and
mc_info.  fru is new data from ipmitool fru print.  mc_info is the
current ipmi_mc_info  fact.  I have updated the ipmi_mc_info fact so
that it uses this new structured fact.

The new fact will look like the following:

```
{
  fru => {
    board_mfg_date => "Tue Mar  3 21:43:00 2015",
    board_mfg => "DELL",
    board_product => "PowerEdge R220",
    board_serial => "*********",
    board_part_number => "0DRXF5A04",
    product_manufacturer => "DELL",
    product_name => "Test",
    product_extra => "*********"
  },
  mc_info => {
    IPMI_Puppet_Service_Recommend => "running",
    Device ID => "32",
    Device Revision => "1",
    Firmware Revision => "2.65",
    IPMI Version => "2.0",
    Manufacturer ID => "674",
    Manufacturer Name => "DELL Inc",
    Product ID => "256 (0x0100)",
    Product Name => "Unknown (0x100)",
    Device Available => "yes",
    Provides Device SDRs => "yes"
  }
}
```

We are able to use commands like the following:
set the board_product with:
* sudo ipmitool fru edit 0 field b 1

And the product_name with:
* sudo ipmitool fru edit 0 field p 1
  • Loading branch information
b4ldr committed Feb 14, 2024
1 parent b994667 commit ded7578
Show file tree
Hide file tree
Showing 4 changed files with 176 additions and 49 deletions.
48 changes: 48 additions & 0 deletions lib/facter/ipmitool.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

Facter.add(:ipmitool, type: :aggregate) do
# https://puppet.com/docs/puppet/latest/fact_overview.html
confine kernel: 'Linux'
confine is_virtual: false
# TODO: consider confining based on which
# this has the side affect that the ipmitool fact and ipmitool_mc_info facts would be Nil
# if ipmi is not present instead of the curent values of
# ipmitool: {"fru"=>{}, "mc_info"=>{"IPMI_Puppet_Service_Recommend"=>"stopped"}}
# ipmitool_mc_info: {"IPMI_Puppet_Service_Recommend"=>"stopped"}
# confine do
# Facter::Util::Resolution.which('ipmitool')
# end

ipmitool_present = Facter::Util::Resolution.which('ipmitool')
chunk(:fru) do
retval = { fru: {} }
if ipmitool_present
ipmitool_output = Facter::Util::Resolution.exec('ipmitool fru print 0 2>/dev/null')
ipmitool_output.each_line do |line|
next unless line.include?(':')

info = line.split(':', 2)
next if info[1].strip.empty?

key = info[0].strip.tr("\s", '_').downcase
retval[:fru][key] = info[1].strip
end
end
retval
end

chunk(:mc_info) do
retval = { mc_info: { 'IPMI_Puppet_Service_Recommend' => 'stopped' } }
if ipmitool_present
ipmitool_output = Facter::Util::Resolution.exec('ipmitool mc info 2>/dev/null')

ipmitool_output.each_line do |line|
info = line.split(':')
retval[:mc_info][info[0].strip] = info[1].strip if info.length == 2 && (info[1].strip != '')
end
retval[:mc_info]['IPMI_Puppet_Service_Recommend'] = 'running' if retval[:mc_info].fetch('Device Available', 'no') == 'yes'
end
retval
end
end
16 changes: 1 addition & 15 deletions lib/facter/ipmitool_mc_info.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,7 @@
Facter.add(:ipmitool_mc_info) do
# https://puppet.com/docs/puppet/latest/fact_overview.html
confine kernel: 'Linux'

retval = {}
retval['IPMI_Puppet_Service_Recommend'] = 'stopped'

if Facter::Util::Resolution.which('ipmitool')
ipmitool_output = Facter::Util::Resolution.exec('ipmitool mc info 2>/dev/null')

ipmitool_output.each_line do |line|
info = line.split(':')
retval[info[0].strip] = info[1].strip if info.length == 2 && (info[1].strip != '')
end
retval['IPMI_Puppet_Service_Recommend'] = 'running' if retval.fetch('Device Available', 'no') == 'yes'
end

setcode do
retval
Facter.value('ipmitool')[:mc_info]
end
end
105 changes: 105 additions & 0 deletions spec/unit/facter/ipmitool.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# frozen_string_literal: true

require 'spec_helper'
require 'facter'

describe 'ipmitool', type: :fact do
subject(:fact) { Facter.fact(:ipmitool) }

before do
# perform any action that should be run before every test
Facter.clear
Facter.fact(:kernel).stubs(:value).returns('Linux')
Facter.fact(:is_virtual).stubs(:value).returns(false)
end

let(:fru_output) do
<<~OUTPUT
Board Mfg Date : Tue Mar 3 21:43:00 2015
Board Mfg : DELL
Board Product : PowerEdge R220
Board Serial : 000000
Board Part Number : 0DRXF5A04
Product Manufacturer : DELL
Product Name : Test
Product Extra : 000000
OUTPUT
end
let(:mc_output) do
<<~SAMPLE
Device ID : 32
Device Revision : 1
Firmware Revision : 2.49
IPMI Version : 2.0
Manufacturer ID : 10876
Manufacturer Name : Supermicro
Product ID : 43707 (0xaabb)
Product Name : Unknown (0xAABB)
Device Available : yes
Provides Device SDRs : no
Additional Device Support :
Sensor Device
SDR Repository Device
SEL Device
FRU Inventory Device
IPMB Event Receiver
IPMB Event Generator
Chassis Device
Aux Firmware Rev Info :
0x00
0x00
0x00
0x00
SAMPLE
end

context 'with no ipmitool' do
before do
Facter::Util::Resolution.expects(:which).at_least(1).with('ipmitool').returns(nil)
Facter::Util::Resolution.expects(:exec).with('ipmitool mc info 2>/dev/null').never
Facter::Util::Resolution.expects(:exec).with('ipmitool fru print 0 2>/dev/null').never
end

it do
expect(fact.value).to eq({ 'fru' => {}, 'mc_info' => { 'IPMI_Puppet_Service_Recommend' => 'stopped' } })
end
end

context 'with detailed output' do
before do
Facter::Util::Resolution.expects(:which).with('ipmitool').returns(true)
Facter::Util::Resolution.expects(:exec).with('ipmitool mc info 2>/dev/null').returns(mc_output)
Facter::Util::Resolution.expects(:exec).with('ipmitool fru print 0 2>/dev/null').returns(fru_output)
end

it do
expect(fact.value).to eq(
{
'mc_info' => {
'Device ID' => '32',
'Device Revision' => '1',
'Firmware Revision' => '2.49',
'IPMI Version' => '2.0',
'IPMI_Puppet_Service_Recommend' => 'running',
'Manufacturer ID' => '10876',
'Manufacturer Name' => 'Supermicro',
'Product ID' => '43707 (0xaabb)',
'Product Name' => 'Unknown (0xAABB)',
'Device Available' => 'yes',
'Provides Device SDRs' => 'no',
},
'fru' => {
'board_mfg_date' => 'Tue Mar 3 21:43:00 2015',
'board_mfg' => 'DELL',
'board_product' => 'PowerEdge R220',
'board_serial' => '000000',
'board_part_number' => '0DRXF5A04',
'product_manufacturer' => 'DELL',
'product_name' => 'Test',
'product_extra' => '000000',
}
}
)
end
end
end
56 changes: 22 additions & 34 deletions spec/unit/facter/ipmitool_mc_info_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,51 +10,39 @@
before do
# perform any action that should be run before every test
Facter.clear
Facter.fact(:kernel).stubs(:value).returns('Linux')
end

let(:detailed_output) do
<<~SAMPLE
Device ID : 32
Device Revision : 1
Firmware Revision : 2.49
IPMI Version : 2.0
Manufacturer ID : 10876
Manufacturer Name : Supermicro
Product ID : 43707 (0xaabb)
Product Name : Unknown (0xAABB)
Device Available : yes
Provides Device SDRs : no
Additional Device Support :
Sensor Device
SDR Repository Device
SEL Device
FRU Inventory Device
IPMB Event Receiver
IPMB Event Generator
Chassis Device
Aux Firmware Rev Info :
0x00
0x00
0x00
0x00
SAMPLE
end

context 'with no ipmitool' do
context 'with no ipmitool fact' do
before do
Facter::Util::Resolution.expects(:which).at_least(1).with('ipmitool').returns(nil)
Facter::Util::Resolution.expects(:exec).with('ipmitool mc info 2>/dev/null').never
Facter.fact(:ipmitool).stubs(:value).returns(nil)
end

it do
expect(fact.value).to eq({ 'IPMI_Puppet_Service_Recommend' => 'stopped' })
expect(fact.value).to be_nil
end
end

context 'with detailed output' do
before do
Facter::Util::Resolution.expects(:which).with('ipmitool').returns('ipmitool')
Facter::Util::Resolution.expects(:exec).with('ipmitool mc info 2>/dev/null').returns(detailed_output)
Facter.fact(:ipmitool).stubs(:value).returns(
{
fru: {},
mc_info: {
'Device ID' => '32',
'Device Revision' => '1',
'Firmware Revision' => '2.49',
'IPMI Version' => '2.0',
'IPMI_Puppet_Service_Recommend' => 'running',
'Manufacturer ID' => '10876',
'Manufacturer Name' => 'Supermicro',
'Product ID' => '43707 (0xaabb)',
'Product Name' => 'Unknown (0xAABB)',
'Device Available' => 'yes',
'Provides Device SDRs' => 'no',
}
}
)
end

it do
Expand Down

0 comments on commit ded7578

Please sign in to comment.