neatest way to determine a major version of centos/linux?

4,091 views
Skip to first unread message

Dick Davies

unread,
Feb 3, 2012, 11:57:34 AM2/3/12
to puppet...@googlegroups.com
Just started a rollout of centos 6.x across our Puppet deployment
(100-odd servers).

what fact would people suggest I use to distinguish 5.x from 6.x
(quite a lot of subsystems are different between major releases)?

lsb* facts don't seem to be present on centos 6 - is this an EPEL bug,
or have they
just been removed in Facter?

Thanks!

Christopher Wood

unread,
Feb 3, 2012, 12:00:18 PM2/3/12
to puppet...@googlegroups.com
This sort of thing works satisfactorily if cumbersomely for me:

case $::operatingsystemrelease {
/^5/: {

}
/^6/: {

}
}

> --
> You received this message because you are subscribed to the Google Groups "Puppet Users" group.
> To post to this group, send email to puppet...@googlegroups.com.
> To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.
>
>

Jeff McCune

unread,
Feb 3, 2012, 12:18:58 PM2/3/12
to puppet...@googlegroups.com
On Fri, Feb 3, 2012 at 8:57 AM, Dick Davies <rasp...@hellooperator.net> wrote:
Just started a rollout of centos 6.x across our Puppet deployment
(100-odd servers).

what fact would people suggest I use to distinguish 5.x from 6.x
(quite a lot of subsystems are different between major releases)?

They'll be there if you have the redhat-lsb package installed.  I'd use the lsbmajdistrelease fact.

root@pe-centos6:~# facter | grep lsb
lsbdistcodename => Final
lsbdistdescription => CentOS release 6.1 (Final)
lsbdistid => CentOS
lsbdistrelease => 6.1
lsbmajdistrelease => 6
lsbrelease => :core-4.0-ia32:core-4.0-noarch:graphics-4.0-ia32:graphics-4.0-noarch:printing-4.0-ia32:printing-4.0-noarch
root@pe-centos6:~# rpm -qilp `which lsb_release`
error: /usr/bin/lsb_release: not an rpm package (or package manifest)


root@pe-centos6:~# rpm -qif `which lsb_release`
Name        : redhat-lsb                   Relocations: (not relocatable)
Version     : 4.0                               Vendor: CentOS
Release     : 3.el6.centos                  Build Date: Sun 20 Nov 2011 01:44:34 PM PST
Install Date: Thu 15 Dec 2011 01:22:18 PM PST      Build Host: c6b5.bsys.dev.centos.org
Group       : System Environment/Base       Source RPM: redhat-lsb-4.0-3.el6.centos.src.rpm
Size        : 22558                            License: GPL
Signature   : RSA/SHA1, Mon 21 Nov 2011 04:54:30 PM PST, Key ID 0946fca2c105b9de
Packager    : CentOS BuildSystem <http://bugs.centos.org>
Summary     : LSB base libraries support for CentOS
Description :
The Linux Standard Base (LSB) is an attempt to develop a set of
standards that will increase compatibility among Linux distributions.
The redhat-lsb package provides utilities needed for LSB Compliant
Applications.  It also contains requirements that will ensure that all
components required by the LSB that are provided by CentOS are
installed on the system.
 
-- 
Jeff McCune


Ramin K

unread,
Feb 3, 2012, 12:29:02 PM2/3/12
to Puppet Users
You'll need to add the redhat-lsb package to your kickstart system and/
or just install it on your current systems. That's the package facter
uses to determine the lsb facts.

Monkeys Typing

unread,
Feb 7, 2012, 2:29:47 PM2/7/12
to Puppet Users
I disliked all the dependencies that the -lsb package pulled onto my
servers, like CUPS and X. So I just created a custom fact with the
code that has been used since el3 to determine a release:

Facter.add("release") do
setcode do
%x{cat /etc/redhat-release | awk -Frelease {'print $2'} | awk
{'print $1'} | awk -F. {'print $1'}}.chomp
end
end

Not any more elegant than the /^5/ matching, but I am happy with it.

Jim Goddard

technop...@gmail.com

unread,
Feb 7, 2012, 9:37:03 PM2/7/12
to Puppet Users
I use this:

Facter.add("operatingsystemrelease_mv") do
setcode do
%x{cat /etc/redhat-release |awk \{'print $3'\}|cut -
c1}.chomp
end
end

Dick Davies

unread,
Feb 10, 2012, 6:59:43 AM2/10/12
to puppet...@googlegroups.com
Thanks all, there should be enough in the replies to get me going :)

Want to use hiera for determining package names etc between major
versions (e.g. sendmail on 5.x, postfix on 6.x)

- will look up based on OS_flavour+ major_release
(Centos-5.json, RHEL-6.json, etc.) and that should get me sorted.

Thanks a lot!

Elias Abacioglu

unread,
Feb 12, 2012, 5:12:55 PM2/12/12
to puppet...@googlegroups.com
> On 8 February 2012 02:37, d...@looprock.com<technop...@gmail.com> wrote:
> I use this:
>
> Facter.add("operatingsystemrelease_mv") do
> setcode do
> %x{cat /etc/redhat-release |awk \{'print $3'\}|cut -
> c1}.chomp
> end
> end
>

I think that will fail on centos. This line is better, works on
centos/rhel.

Gary Larizza

unread,
Feb 12, 2012, 7:25:09 PM2/12/12
to puppet...@googlegroups.com
There's also the 'operatingsystemrelease' fact that will evaluate to the full version.  You could do this:

Facter.add('operatingsystemmajor') do
  setcode do
    Facter.value('operatingsystemrelease').split('.').first
  end
end


If you do choose to use the shell command, you can do this:

Facter.add('operatingsystemmajor') do
  setcode("cat /etc/redhat-release | awk \{'print $3'\}|cut - c1")
end

Passing a string to the setcode method in Facter will automatically pipe the command to Facter::Util::Resolution.exec which will execute the command and return the value from stdout.  Using Facter::Util::Resolution.exec() is better than %x{} because it has a built-in timeout (so if your command hangs your facter/puppet run won't).  It also handles nil values well, has a built-in PATH environment variable, and handles invalid commands a bit better than %x{}  (plus, just passing an argument to setcode is a bit cleaner).



On Sun, Feb 12, 2012 at 2:12 PM, Elias Abacioglu <elias...@gmail.com> wrote:
On 8 February 2012 02:37, d...@looprock.com<technopatholog...@gmail.com>  wrote:
I use this:

Facter.add("operatingsystemrelease_mv") do
       setcode do
               %x{cat /etc/redhat-release |awk \{'print $3'\}|cut -
c1}.chomp
       end
end


I think that will fail on centos. This line is better, works on centos/rhel.

cat /etc/redhat-release |awk -Frelease {'print $2'}  | awk {'print $1'} | awk -F. {'print $1'}

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.




--

Gary Larizza
Professional Services Engineer
Puppet Labs

technop...@gmail.com

unread,
Feb 13, 2012, 11:30:33 AM2/13/12
to Puppet Users
Elias,

cat '/etc/redhat-release |awk {'print $3'}|cut -c1' works fine under
redhat and centos, however I just tested it and it's worth noting that
it doesn't work under scientific linux.

Gary,

Using the facter value is great, thanks. I didn't think of doing this.
It's by far the neatest and most elegant way to do this. Always good
to push the heavy lifting upstream. :)

On Feb 12, 6:25 pm, Gary Larizza <g...@puppetlabs.com> wrote:
> There's also the 'operatingsystemrelease' fact that will evaluate to the
> full version.  You could do this:
>
> Facter.add('operatingsystemmajor') do
>   setcode do
>     Facter.value('operatingsystemrelease').split('.').first
>   end
> end
>
> If you do choose to use the shell command, you can do this:
>
> Facter.add('operatingsystemmajor') do
>   setcode("cat /etc/redhat-release | awk \{'print $3'\}|cut - c1")
> end
>
> Passing a string to the setcode method in Facter will automatically pipe
> the command to Facter::Util::Resolution.exec which will execute the command
> and return the value from stdout.  Using Facter::Util::Resolution.exec() is
> better than %x{} because it has a built-in timeout (so if your command
> hangs your facter/puppet run won't).  It also handles nil values well, has
> a built-in PATH environment variable, and handles invalid commands a bit
> better than %x{}  (plus, just passing an argument to setcode is a bit
> cleaner).
>
> On Sun, Feb 12, 2012 at 2:12 PM, Elias Abacioglu <elias.r...@gmail.com>wrote:
>
>
>
>
>
>
>
>
>
> > On 8 February 2012 02:37, d...@looprock.com<technopatholo*...@gmail.com<technopathol...@gmail.com>>
> >>  wrote:
> >> I use this:
>
> >> Facter.add("**operatingsystemrelease_mv") do
> >>        setcode do
> >>                %x{cat /etc/redhat-release |awk \{'print $3'\}|cut -
> >> c1}.chomp
> >>        end
> >> end
>
> > I think that will fail on centos. This line is better, works on
> > centos/rhel.
>
> > cat /etc/redhat-release |awk -Frelease {'print $2'}  | awk {'print $1'} |
> > awk -F. {'print $1'}
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Puppet Users" group.
> > To post to this group, send email to puppet...@googlegroups.com.
> > To unsubscribe from this group, send email to puppet-users+unsubscribe@**
> > googlegroups.com <puppet-users%2Bunsu...@googlegroups.com>.
> > For more options, visit this group athttp://groups.google.com/**
> > group/puppet-users?hl=en<http://groups.google.com/group/puppet-users?hl=en>
> > .

Jeffrey Watts

unread,
Feb 13, 2012, 12:17:33 PM2/13/12
to puppet...@googlegroups.com
Gary, I've been solving this problem by using the following inline_template in the modules that need to get the major release version:
$os_major_ver = inline_template("<%= operatingsystemrelease.split('.')[0] %>")

I'm new to Puppet, and I like the elegance of your example below - to implement it, would I need to put that block in <modulename>/lib/facter/operatingsystemmajor.rb?  I assume I'd need to put that in every module that'd use it.  Is there a better way?  I currently use that block in 3 or 4 modules.

Thanks!
Jeffrey.

Gary Larizza

unread,
Feb 13, 2012, 12:29:50 PM2/13/12
to puppet...@googlegroups.com
On Mon, Feb 13, 2012 at 9:17 AM, Jeffrey Watts <jeffrey...@gmail.com> wrote:
Gary, I've been solving this problem by using the following inline_template in the modules that need to get the major release version:
$os_major_ver = inline_template("<%= operatingsystemrelease.split('.')[0] %>")

I'm new to Puppet, and I like the elegance of your example below - to implement it, would I need to put that block in <modulename>/lib/facter/operatingsystemmajor.rb?  I assume I'd need to put that in every module that'd use it.  Is there a better way?  I currently use that block in 3 or 4 modules.

Thanks!
Jeffrey.


Hi Jeffrey,

You're correct about the placement of the file, however you don't need to include it in EVERY module you use.  That fact only needs to be in ONE of your modules for every node to utilize it as a Facter fact (currently, ANY Facter facts that are in your $modulepatch get loaded by ALL of your nodes).

So repeating this code is very redundant.  Does this makes sense?




On Sun, Feb 12, 2012 at 6:25 PM, Gary Larizza <ga...@puppetlabs.com> wrote:
There's also the 'operatingsystemrelease' fact that will evaluate to the full version.  You could do this:

Facter.add('operatingsystemmajor') do
  setcode do
    Facter.value('operatingsystemrelease').split('.').first
  end
end

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.

Gary Larizza

unread,
Feb 13, 2012, 12:30:16 PM2/13/12
to puppet...@googlegroups.com
* $modulepath NOT $modulepatch

Jeffrey Watts

unread,
Feb 13, 2012, 12:36:19 PM2/13/12
to puppet...@googlegroups.com
Yes, thanks.  My only concern though is that catalogs will fail to compile if that particular module that it's located in isn't included in that node definition.  I worry that any successors will not be able to easily figure out what I've done.

Could I create a module named "global" and have it simply be where things like that live?  What's the minimum I'd need to have in it?  An init.pp with simply "class global { }"?  Are there other, better ways?

Thanks again,
Jeffrey.

Gary Larizza

unread,
Feb 13, 2012, 12:43:52 PM2/13/12
to puppet...@googlegroups.com
Hey Jeffrey,

Yes, many sites have a 'stdlib' or 'global' that contains custom facts, functions, types/providers, and the like.  You wouldn't even need a class declaration at all, you could just have a directory called 'global' that has lib/facter/{facts here} in it.  As long as that global module is in the $modulepath, then all of your nodes have their custom facts.

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.

Gary Larizza

unread,
Feb 13, 2012, 12:48:00 PM2/13/12
to puppet...@googlegroups.com
On Mon, Feb 13, 2012 at 9:36 AM, Jeffrey Watts <jeffrey...@gmail.com> wrote:
Yes, thanks.  My only concern though is that catalogs will fail to compile if that particular module that it's located in isn't included in that node definition.  I worry that any successors will not be able to easily figure out what I've done.


And I don't think I've cleared this up for you - you DON'T NEED TO INCLUDE the class in a node declaration for a node to have that module's custom facts loaded and available to your node.  For example, if this fact lived in the mysql module, you DO NOT NEED to have 'include mysql' in the node declaration for the node to have access to the custom fact.  Custom facts get synced down to the clients via Pluginsync, and ALL custom facts that are in ANY modules in your $modulepath will automatically get synced down to ALL Puppet nodes BEFORE Puppet starts running REGARDLESS of whether that module's classes are declared in a node declaration.  

BTW, don't misinterpret the emphasis for yelling - just trying to emphasize specific points that I might have glossed-over previously :)
 
Could I create a module named "global" and have it simply be where things like that live?  What's the minimum I'd need to have in it?  An init.pp with simply "class global { }"?  Are there other, better ways?

Thanks again,
Jeffrey.


On Mon, Feb 13, 2012 at 11:29 AM, Gary Larizza <ga...@puppetlabs.com> wrote:

Hi Jeffrey,

You're correct about the placement of the file, however you don't need to include it in EVERY module you use.  That fact only needs to be in ONE of your modules for every node to utilize it as a Facter fact (currently, ANY Facter facts that are in your $modulepatch get loaded by ALL of your nodes).

So repeating this code is very redundant.  Does this makes sense?

--
You received this message because you are subscribed to the Google Groups "Puppet Users" group.
To post to this group, send email to puppet...@googlegroups.com.
To unsubscribe from this group, send email to puppet-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/puppet-users?hl=en.

Jeffrey Watts

unread,
Feb 13, 2012, 12:57:10 PM2/13/12
to puppet...@googlegroups.com
Oh, that really clears it up.  Thanks!

Jeffrey.
Reply all
Reply to author
Forward
0 new messages