http://www.zabbix.com/wiki/doku.php?id=howto:dellipmi
IPMI on Dell Servers
The following article outlines how to use Zabbix to monitor the information from Dell PowerEdge Servers without an agent, using the Dell BMC via IP. I’ve done with with PowerEdge 1850, 1950, 2850, 2950 servers, some with DRAC4 cards at the The Frontier School Division . Questions/problems with the article? Email me at [email protected].
IPMI on the BMC is not enabled over IP by default on Dell PE servers. You can enable IPMI over IP in the BIOS, or via a DRAC5 controller if you have it installed. Carlos' Corner blog with screenshots of IPMI IP setup on a DRAC5 card
Steps to Enable IPMI over IP
Note: You do not get a ping reply from the BMC over IP. You will need to use IPMItool (See below) to query the BMC.
You’ll need to install ipmitool, which is in the OpenIPMI-tools package. On CentOS, you can use:
yum install OpenIPMI-tools
to install, auto launch, and start the service. (You may only need OpenIPMI-tools) On other distro’s, you’ll need to find the OpenIPMI-tools package & install it.
Use the following command to query the remote BMC:
/usr/bin/ipmitool -H BMC_REMOTE_IP -U username -P password -I lan -L USER sdr
BMC_REMOTE_IP=IP address assigned to the BMC.
username/password=Username/password assigned on the BMC.
sdr=reports on various hardware sensors. Other options are sel for system event log, and fru for hardware information.
Now the question is how to take this data, and bring it into Zabbix. Here’s a sample of a portion of the ipmitool sdr readout:
Temp | 30 degrees C | ok Temp | disabled | ns Ambient Temp | 19 degrees C | ok Planar Temp | 30 degrees C | ok Riser Temp | 29 degrees C | ok Temp | disabled | ns Temp | disabled | ns CMOS Battery | 3.11 Volts | ok FAN 1A RPM | 7350 RPM | ok FAN 1B RPM | 5025 RPM | ok FAN 2A RPM | 7500 RPM | ok FAN 2B RPM | 5025 RPM | ok FAN 3A RPM | 7425 RPM | ok FAN 3B RPM | 5175 RPM | ok FAN 4A RPM | 7725 RPM | ok FAN 4B RPM | 5175 RPM | ok
Cron Data Dump
This is only a small portion of what reads out. Data readout from the BMC is also quite slow. I believe it’s using a 2400 baud serial connection that shifts to IP. This becomes a problem for bringing into Zabbix, as the Zabbix agent will time out on a script that reads directly from the BMC.
To solve this, we’ll create a cron job that pulls the data, & puts it into a text file every 3 minutes. edit /etc/crontab & add the following line:
*/3 * * * * root /etc/zabbix/ipmidump.sh
This will run the script at /etc/zabbix/ipmidump.sh as root every 3 minutes. Here’s an example of my ipmidump.sh script:
#!/bin/bash /usr/bin/ipmitool -H server1_IP -U username -P password -I lan -L USER sdr>/etc/zabbix/server1.dump.$ cp /etc/zabbix/server1.dump.$ /etc/zabbix/server1.dump /usr/bin/ipmitool -H server2_IP -U username -P password -I lan -L USER sdr>/etc/zabbix/server2.dump.$ cp /etc/zabbix/server2.dump.$ /etc/zabbix/server2.dump
The script runs the IMPItool dump & places it into a temporary text file, and then copies that file to it’s permanent location. Repeat as needed for the number of servers you want to use IPMI for.
Parsing Data from the dump Now we need a script that we can use with the Zabbix agent that will pull the data we want out of the dump. Parse data from IPMI SDR Readout script (Credit to Rick Wagner for providing the Perl script. [email protected])
#!/usr/bin/perl # Script provided for Zabbix community by Rick Wagner ([email protected]) use strict; use warnings; die usage( ) if ( $#ARGV == -1); my $regex = qr /\s *\|\s */; my $val ; #my $OUTPUT; if ( open ( FILE, "< /etc/zabbix/server1.dump" ) ) { while ( <FILE> ) { chomp ( $_ ) ; my @fields = split ( /$regex /,$_ ) ; #print $fields[0]; if ( $#fields >= 2 && $ARGV[0] eq $fields[0]) { last if ( $fields [ 2 ] eq 'ns' ) ; $val = $fields [ 1 ] ; last ; } } } else { die "Error:. $!\n " ; } if ( defined ( $val ) ) { ( $val ) = ( $val =~ /^( \d+) \s +/) ; print $val ."\n " ; exit ( 0 ) ; } else { exit ( -1 ) ; } sub usage { return "Usage: ./$0 <key>" }
Usage: /etc/zabbix/server1.pl ‘Parameter’
/etc/zabbix/server1.pl 'Ambient Temp' (Returns 19) /etc/zabbix/server1.pl 'FAN 1A RPM' (Returns 7350)
Linking to Zabbix Agent
Edit your zabbix_agentd.conf file & add the following UserParameter lines to the end of the file:
UserParameter=server1.ambtemp,/etc/zabbix/server1.pl 'Ambient Temp' UserParameter=server1.fan1,/etc/zabbix/server1.pl 'FAN 1 RPM'
Restart the agent. You can now query the Zabbix agent with:
zabbix_agentd -t server1.ambtemp And you will see: server1.ambtemp [t|19]
Because we have added the custom queries to the IPMI into your zabbix server’s zabbix_agentd, you will need to add the items to your Zabbix Server Under Configuration/Items.
You will now have history for whatever items you wish to add. I use IPMI for temperatures, and fan monitoring. Because the data dump takes over 60 seconds, I only have the cron running every 180 seconds.
Good luck! Hopefully the time I spent getting this working will save you a lot of time in return.
The zabbix template to use with this perl script can be found here or on the templates page.
I guess the comments in the perl script speak for themselves, the script can easily be extended to report more data, but I am only interested in the fans and temperatures at the moment. Feel free to post improvements.
#!/usr/bin/perl ######################################################################### # The purpose of the perl script is to parse the output of ipmitool and # # send it to a zabbix server, no zabbix_agent needed # # # # You need to have impitool installed to use this script # # # # Suggested usage is to run this script from a cronjob # # # # Have fun with it, Emiel Witteman # ######################################################################### use strict; use warnings; use IO::Socket ; use IO::Select ; use MIME::Base64 ; ################# # Configuration # ################# my $zabbixserver = "zabbix.somewhere.lan" ; my $zabbixport = "10051" ; my $zabbixhost = "myhost" ; my $fieldsep = qr /\s *\|\s */; my $i =0 ; my $tempnr =0 ; my @IPMI =split ( /\n/,`ipmitool sensor`) ; while ( $IPMI [ $i ] ) { my @fields = split ( /$fieldsep /,$IPMI [ $i ] ) ; ############### # Report FANs # ############### #output from ipmitool: #FAN 1 RPM | 5250.000 | RPM | ok | na | 2025.000 | na | na | na | na #FAN 2 RPM | 5250.000 | RPM | ok | na | 2025.000 | na | na | na | na #FAN 3 RPM | 5400.000 | RPM | ok | na | 2025.000 | na | na | na | na #FAN 4 RPM | 5250.000 | RPM | ok | na | 2025.000 | na | na | na | na #FAN 5 RPM | 4200.000 | RPM | ok | 14400.000 | na | 0.000 | 0.000 | na | na #FAN 6 RPM | 4200.000 | RPM | ok | 14400.000 | na | 0.000 | 0.000 | na | na if ( $fields [ 0 ] =~ /FAN/) { # print "DEBUG: $fields[0],$fields[1],$fields[2],$fields[3],$fields[4]\n"; $fields [ 0 ] =~ s /RPM//; #remove "RPM" $fields [ 0 ] =~ s /^\s +|\s +$//g; #remove starting/trailing whitespace $fields [ 0 ] =~ s /\s /_/g; #substitute whitespace by _ $fields [ 0 ] = lc ( $fields [ 0 ] ) ; #make lowercase &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0].rpm" , $fields [ 1 ] ) ; if ( $fields [ 3 ] =~ /^ok$/) { &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0].status" , 1 ) ; } else { &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0].status" , 0 ) ; } } ################ # Report Temps # ################ #output from ipmitool: #Temp | -52.000 | degrees C | ok | na | na | na | 85.000 | 90.000 | na #Temp | 50.000 | degrees C | ok | na | na | na | 85.000 | 90.000 | na #Temp | 40.000 | degrees C | ok | 64.000 | na | -128.000 | -128.000 | na | na #Temp | 40.000 | degrees C | ok | 64.000 | na | -128.000 | -128.000 | na | na #Ambient Temp | 23.000 | degrees C | ok | na | 3.000 | 8.000 | 42.000 | 47.000 | na if ( $fields [ 0 ] =~ /^Temp$/) { if ( $tempnr >0 ) { $fields [ 0 ] = lc ( $fields [ 0 ] ) ; #make lowercase # print "DEBUG: $fields[0],$fields[1],$fields[2],$fields[3],$fields[4]\n"; &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0]$tempnr" , $fields [ 1 ] ) ; if ( $fields [ 3 ] =~ /^ok$/) { &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0]$tempnr.status" , 1 ) ; } else { &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0]$tempnr.status" , 0 ) ; } } $tempnr ++; } if ( $fields [ 0 ] =~ /^Ambient Temp$/) { $fields [ 0 ] =~ s /\s /_/g; #substitute whitespace by _ $fields [ 0 ] = lc ( $fields [ 0 ] ) ; #make lowercase # print "DEBUG: $fields[0],$fields[1],$fields[2],$fields[3],$fields[4]\n"; &zabbix_sender( $zabbixserver , $zabbixhost , "sensor.$fields[0]" , $fields [ 1 ] ) ; # if ($fields[3] =~ /^ok$/){ # &zabbix_sender($zabbixserver, $zabbixhost, "sensor.$fields[0].status", 1); # } else { # &zabbix_sender($zabbixserver, $zabbixhost, "sensor.$fields[0].status", 0); # } } $i ++; } sub zabbix_sender { my ( $zabbixserver ,$hostname ,$item ,$data ) = @_ ; my $timeout =10 ; my $result ; my $request =sprintf ( "<req>\n <host>%s</host>\n <key>%s</key>\n <data>%s</data>\n </req>\n " , encode_base64( $hostname ) ,encode_base64( $item ) ,encode_base64( $data ) ) ; my $sock = new IO::Socket ::INET ( PeerAddr => $zabbixserver , PeerPort => '10051' , Proto => 'tcp' , Timeout => $timeout ) ; die "Could not create socket: $!\n " unless $sock ; $sock ->send ( $request ) ; my @handles =IO::Select ->new ( $sock ) ->can_read ( $timeout ) ; if ( scalar ( @handles ) > 0 ) { $sock ->recv ( $result ,1024 ) ; if ( $result ne "OK" ) { #only print response if not OK print "answer from zabbix server $zabbixserver: $result\n " ; } } else { print "no answer from zabbix server\n " ; } $sock ->close ( ) ; }