Module interaction and dependencies in Puppet (SNMP in particular)

174 views
Skip to first unread message

Duncan Hill

unread,
Jul 2, 2008, 6:34:00 AM7/2/08
to puppet...@googlegroups.com
Hello folks,

I'm sitting here converting my static, simple classes/snmp.pp into a
full module, and I've run into a bit of a brick wall.

net-snmp is one of those wonderful programs that will only read two
configuration files (it reads a few more, but only 2 are in /etc) -
/etc/snmpd.conf and /etc/snmpd.local.conf. This means that my SNMP
module is somehow going to have to interact with my HP Managed module,
as a server with HP management will have some extra lines in the SNMP
configuration. However, I've also got Java SNMP stuff, which I'm
currently stuffing into the local file.

So, my base snmpd.conf.erb file looks something like:
# Contact details, location details
syscontact <%= snmp_syscontact %>
syslocation <%= snmp_syslocation %>

HP managed (currently a class, should become a module) means I need to
add stuff like:
dlmod cmaX /usr/lib<%= arch %>/libcmaX<%= arch %>.so
<% if rwcommunities.length > 0 %> <%% Only parse if we have ips %>
# Read/write communities
<% rwcommunities.each do |community, ip| %>
<% if ip.is_array %> <%% One community, many IPs %>
<% ip.each do |embip| %>
rwcommunity <%= community %> <%= embip %>
<% end %>
<% else %> <%% One community, one IP %>
rwcommunity <%= community %> <%= ip %>
<% end %>
<% end %>
<% end %>

(I have no clue if that's actually valid yet, I haven't tested it).

Java SNMP (again, a class, should be a module) means I need to add lines like:
<% java_ports.each do |jport| %>
proxy -m /etc/java/JVM-MANAGEMENT-MIB.txt -v2c -c public
localhost:<%=jport%> .1.3.6.1.4.1.42.2.145
<% end %>

What's giving me headaches is how I get all of these components to
play nicely. All servers will have basic SNMP enabled. HP managed
servers need the HP configuration, and Java servers need the java
configuration. Servers have a darn good chance of being both HP and
Java.

Is my only option to write out things like
/etc/snmp/snmpd.base.conf
/etc/snmp/snmpd.hp.conf
/etc/snmp/snmpd.java.conf

and then concatenate the lot into snmpd.conf? The biggest problem I
see here is knowing when to run the concatenation, as I may or may not
have Java, and may/may not have HP managed, so I can't hard-code the
requirements into another module, can I? Is the best approach an
inversion? I.e., set up a node as hp_managed, java::server, and then
in the snmp module, do some kind of 'is this server hp_managed? is
this server a java server?' set of interrogations?

Ashley Penney

unread,
Jul 2, 2008, 7:29:29 AM7/2/08
to puppet...@googlegroups.com
While I haven't tried this, exported resources seem to be the solution for this.  If you look towards the bottom of http://reductivelabs.com/trac/puppet/wiki/CompleteConfiguration, you can see how he concatenates the file from various @@file{}'s throughout other hosts.  Perhaps you can experience with using this to drag all these pieces together into a single file?

Thanks,

Duncan Hill

unread,
Jul 2, 2008, 8:48:02 AM7/2/08
to puppet...@googlegroups.com
2008/7/2 Ashley Penney <ape...@gmail.com>:

> While I haven't tried this, exported resources seem to be the solution for
> this. If you look towards the bottom of
> http://reductivelabs.com/trac/puppet/wiki/CompleteConfiguration, you can see
> how he concatenates the file from various @@file{}'s throughout other
> hosts. Perhaps you can experience with using this to drag all these pieces
> together into a single file?

Hmm. Yes, that might work, just have to wrap my head around the
exported stuff. I suppose the next question is will I have a chicken
and egg scenario..

Thanks for the idea.

AJ

unread,
Jul 2, 2008, 8:51:13 AM7/2/08
to puppet...@googlegroups.com
Duncan Hill wrote:
> 2008/7/2 Ashley Penney <ape...@gmail.com>:
>
>> While I haven't tried this, exported resources seem to be the solution for
>> this. If you look towards the bottom of
>> http://reductivelabs.com/trac/puppet/wiki/CompleteConfiguration, you can see
>> how he concatenates the file from various @@file{}'s throughout other
>> hosts. Perhaps you can experience with using this to drag all these pieces
>> together into a single file?
>>

You don't need to use @@files - they are for storedconfigurations, used
to grab files from other clients and drop them on a central one. Simply
make use of David's concatenated_file / concatenated_file_part defines,
in his common module.

I have a consolidated (mostly untested) example at
http://github.com/fujin/module-iptables/tree/master - it unfortunately
does not take into account ordering of concatenated_file_parts (need to
manually put the name to like 1_blah, 2_blah, 3_blah for them to go in
the right order), but otherwise works mysteriously :}

Duncan Hill

unread,
Jul 2, 2008, 9:32:17 AM7/2/08
to puppet...@googlegroups.com
2008/7/2 AJ <a...@junglist.gen.nz>:

> You don't need to use @@files - they are for storedconfigurations, used
> to grab files from other clients and drop them on a central one. Simply
> make use of David's concatenated_file / concatenated_file_part defines,
> in his common module.

Nod, that's the path I was starting to go down. Just have to combine
it with my erb templates for all the various configurations, and then
see what comes out the end.

> I have a consolidated (mostly untested) example at
> http://github.com/fujin/module-iptables/tree/master - it unfortunately

Ordering isn't an issue in this particular case, so I'll take a gander, thanks.

Duncan Hill

unread,
Jul 2, 2008, 10:07:34 AM7/2/08
to puppet...@googlegroups.com
2008/7/2 AJ <a...@junglist.gen.nz>:

> I have a consolidated (mostly untested) example at
> http://github.com/fujin/module-iptables/tree/master - it unfortunately
> does not take into account ordering of concatenated_file_parts (need to
> manually put the name to like 1_blah, 2_blah, 3_blah for them to go in
> the right order), but otherwise works mysteriously :}

One question about 'iptables::concatenated_file' - how do you (do
you?) use an object reference to this? Ie, if I want to subscribe
snmpd to it (yeah, I could use notify), Puppet complains about the ::
in the identifier.

Duncan Hill

unread,
Jul 2, 2008, 11:11:42 AM7/2/08
to puppet...@googlegroups.com
2008/7/2 Duncan Hill <baja...@googlemail.com>:

> Hello folks,
>
> I'm sitting here converting my static, simple classes/snmp.pp into a
> full module, and I've run into a bit of a brick wall.
> dlmod cmaX /usr/lib<%= arch %>/libcmaX<%= arch %>.so
> <% if rwcommunities.length > 0 %> <%% Only parse if we have ips %>
> # Read/write communities
> <% rwcommunities.each do |community, ip| %>
> <% if ip.is_array %> <%% One community, many IPs %>
> <% ip.each do |embip| %>
> rwcommunity <%= community %> <%= embip %>
> <% end %>
> <% else %> <%% One community, one IP %>
> rwcommunity <%= community %> <%= ip %>
> <% end %>
> <% end %>
> <% end %>
>
> (I have no clue if that's actually valid yet, I haven't tested it).

It turns out this isn't valid, and I suspect that it's mostly because
I haven't grokked Ruby and associative arrays properly.

I've tried the following syntaxes in the recipe:
$rwcommunities = ( "private" => "127.0.0.1" )
$rwcommunities = [ "private" => "127.0.0.1" ]
$rwcommunities = { "private" => "127.0.0.1" }

The erb file prints out
rwcommunity private
rwcommunity 127.0.0.1

So the .each |community, ip| doesn't work in the manner that I'm
expecting. (The is_array got converted to is_a? Array and that
removed the syntax errors.) Clues on the back of a bit as to where
I'm going wrong please - is this just beyond Puppet?

AJ

unread,
Jul 2, 2008, 5:22:37 PM7/2/08
to puppet...@googlegroups.com
*chop*

> I've tried the following syntaxes in the recipe:
> $rwcommunities = ( "private" => "127.0.0.1" )
> $rwcommunities = [ "private" => "127.0.0.1" ]
> $rwcommunities = { "private" => "127.0.0.1" }
>
> The erb file prints out
> rwcommunity private
> rwcommunity 127.0.0.1
>
> So the .each |community, ip| doesn't work in the manner that I'm
> expecting. (The is_array got converted to is_a? Array and that
> removed the syntax errors.) Clues on the back of a bit as to where
> I'm going wrong please - is this just beyond Puppet?
>
I don't believe you can use a ruby Hash in the manifest language. You
can use an array, or a string.

$string = "blah"
$array = [ "blah", "blah" ]

In this case, I'd suggest calling out to something like iClassify from
/inside/ your template, and building everything up from there.

Either that, or pass the values into your template and parse them into a
hash before using it like a hash - nasty - make sense?

Regards,

AJ

Duncan Hill

unread,
Jul 3, 2008, 4:19:38 AM7/3/08
to puppet...@googlegroups.com
2008/7/2 AJ <a...@junglist.gen.nz>:

>
> *chop*
>> I've tried the following syntaxes in the recipe:
>> $rwcommunities = ( "private" => "127.0.0.1" )
>> $rwcommunities = [ "private" => "127.0.0.1" ]
>> $rwcommunities = { "private" => "127.0.0.1" }

> I don't believe you can use a ruby Hash in the manifest language. You


> can use an array, or a string.

Bother. Ok, back to the drawing board. I can define that stuff
statically, but that really doesn't help when I'm trying to write my
modules in a manner that will let me publish them for other people to
use, and in a manner that lets me assign different monitoring IPs and
communities to different machines. Time to read up on iClassify I
guess, though that creates another place to manipulate data to
maintain a server.

Luke (if you're reading),

Do you see hash support in the manifest syntax roadmap at all, or have
you left it out deliberately?

Evan Hisey

unread,
Jul 3, 2008, 10:28:13 AM7/3/08
to puppet...@googlegroups.com
On Thu, Jul 3, 2008 at 3:19 AM, Duncan Hill <baja...@googlemail.com> wrote:
>
> 2008/7/2 AJ <a...@junglist.gen.nz>:
>>
>> *chop*
>>> I've tried the following syntaxes in the recipe:
>>> $rwcommunities = ( "private" => "127.0.0.1" )
>>> $rwcommunities = [ "private" => "127.0.0.1" ]
>>> $rwcommunities = { "private" => "127.0.0.1" }
>
>> I don't believe you can use a ruby Hash in the manifest language. You
>> can use an array, or a string.
>
> Bother. Ok, back to the drawing board. I can define that stuff
> statically, but that really doesn't help when I'm trying to write my
> modules in a manner that will let me publish them for other people to
> use, and in a manner that lets me assign different monitoring IPs and
> communities to different machines. Time to read up on iClassify I
> guess, though that creates another place to manipulate data to
> maintain a server.
>
You can't pass hashes, but you could pass lists and let the template
do a little magic to get what you want in to ruby. <bad pseudo code>
In manifest>>
$rwcommunites= ["private","127.0.0.1","public","196.182.0.1"]

in template >>
<% for each each pair in $rwcommunitess
comunity=$1
ip=$2 %>

rwcommunity <%= community %> <%= ip %>

<% end %>

</bad pseudo code>

You might try something like that for a solution.

Evan

Duncan Hill

unread,
Jul 4, 2008, 5:48:51 AM7/4/08
to puppet...@googlegroups.com
2008/7/3 Evan Hisey <ehi...@gmail.com>:

> You can't pass hashes, but you could pass lists and let the template
> do a little magic to get what you want in to ruby. <bad pseudo code>
> In manifest>>
> $rwcommunites= ["private","127.0.0.1","public","196.182.0.1"]

The solution I picked for this:
$rwcommunities = [ "private:127.0.0.1", "private:192.168.1.1" ]

And in the template:


<% if rwcommunities.length > 0 %>

# Read/write communities
<% rwcommunities.each do |value| %>
<% arr = value.split(':') %>
rwcommunity <%= arr[0] %> <%= arr[1] %>


<% end %>
<% end %>

Cleanish, and consistent for rw, ro and trapsinks.

Evan Hisey

unread,
Jul 4, 2008, 2:46:25 PM7/4/08
to puppet...@googlegroups.com
> The solution I picked for this:
> $rwcommunities = [ "private:127.0.0.1", "private:192.168.1.1" ]
>
> And in the template:
> <% if rwcommunities.length > 0 %>
> # Read/write communities
> <% rwcommunities.each do |value| %>
> <% arr = value.split(':') %>
> rwcommunity <%= arr[0] %> <%= arr[1] %>
> <% end %>
> <% end %>
>
> Cleanish, and consistent for rw, ro and trapsinks.
>
Oh, very clean. I will need to remember this one.

Evan

Duncan Hill

unread,
Jul 5, 2008, 12:37:42 PM7/5/08
to puppet...@googlegroups.com
2008/7/4 Evan Hisey <ehi...@gmail.com>:

>
>> The solution I picked for this:
>> $rwcommunities = [ "private:127.0.0.1", "private:192.168.1.1" ]

>> Cleanish, and consistent for rw, ro and trapsinks.


>>
> Oh, very clean. I will need to remember this one.

The best part is that it enforces the pairing.

It seems like the concatenated file stuff is just the ticket too. My
module for HP's tools will generate one snippet, the SNMP module
generates another, Java can generate a third, and the node manifest
just goes 'concatenate'. It's wonderful :)

Reply all
Reply to author
Forward
0 new messages