Tal como prometí en un post anterior voy a explicar cómo incluí un CGI Perl a la web de administración de Nagios que permite buscar y/o mostrar información almacenada en un fichero.
En ese post habíamos visto cómo, usando el VI Perl Toolkit de VMware, obtener un listado de las máquinas virtuales que tenemos en todos los servidores ESXi de la organización así como si estas máquinas están encendidas o apagadas.
El resultado era algo como esto:
server01.miorganizacion.es,Windows_7_home_x86,poweredOff server01.miorganizacion.es,BT4-R1,poweredOff server01.miorganizacion.es,Ubuntu 10.10,poweredOn server01.miorganizacion.es,XP Act 2010,poweredOff server02.miorganizacion.es,7 ultimate,poweredOff server02.miorganizacion.es,CentOS 5.5,poweredOn server02.miorganizacion.es,Debian 6,poweredOn server02.miorganizacion.es,Win 2003,poweredOn
Cuando el número de VMs empieza a ser elevado resulta útil tener esta información fácilmente accesible por ejemplo desde la web de administración de Nagios:
Como se ve en la imagen, se ha añadido a la columna de la izquierda la opción «VM Search» que tiene un formulario para buscar por el nombre de la máquina virtual o un botón para mostrar todas las máquinas:
Yo uso un «theme» de Nagios que se llama Nuvola Style que da a Nagios una apariencia que me gusta mucho más que la de la instalación por defecto.
Este tema incluye, además de estilos e iconos, un javascript que carga los menus de la parte izquierda y que tendremos que modificar para añadir la opción de «VM Search».
El fichero a editar es:
/usr/share/nagios3/htdocs/side/dtree_data.js
Buscaremos la línea correspondiente a la opción del menú «Event Log» y debajo añadiremos:
reporting.add(13,0,'VM Search',cgipath + 'listvms.cgi','','','side/icons/notes.gif');
El enlace al CGI, vemos que se construye con el «cgipath» que en la configuración de Nagios (en Debian) está definido como:
/usr/lib/cgi-bin/nagios3/
Por tanto, dejamos en este directorio el fichero listvms.cgi cuyo código es:
#!/usr/bin/perl -w # Pintamos la primera parte de la pagina html &start_html; if($ENV{'CONTENT_LENGTH'} == 0) { #No se ha enviado nada por POST, luego cargamos el formulario &print_form; } else { #Se ha enviado algo por POST my $cadena = capture_data(); my @results = search_infile($cadena); if ($#results >= 0) { print_results(\@results); } } &end_html; sub start_html { print "Content-type: text/html\n\n"; print "<html><head>"; print "<title>VM Search</title>"; print "<LINK REL='stylesheet' TYPE='text/css' HREF='/nagios3/stylesheets/common.css'>"; print "<LINK REL='stylesheet' TYPE='text/css' HREF='/nagios3/stylesheets/avail.css'>"; print "<LINK REL='stylesheet' TYPE='text/css' HREF='/nagios3/stylesheets/status.css'>"; print "</head>"; print "<BODY CLASS='avail'>"; print "<table border=0 width=100% cellspacing=0 cellpadding=0>"; print "<tr>"; print "<td align=left valign=top width=33%>"; print " <TABLE CLASS='infoBox' BORDER=1 CELLSPACING=0 CELLPADDING=0>"; print " <TR></TR>"; print " </TABLE>"; print " </td>"; print " <td align=center valign=top width=33%>"; print " </td>"; print " <td align=right valign=bottom width=33%>"; print " <table border=0 CLASS='optBox'>"; print " <tr></tr>"; print " </table>"; print " </td>"; print " </tr>"; print "</table>"; } sub print_form { print '<p></p><div align="center" class="reportSelectTitle">Introduce el término a buscar...</div><p></p>'; print '<p></p><div align="center">'; print "<p>"; print "</p>"; print '<form action="listvms.cgi" method=post>'; print "<input type=text name=virtualmachine size=20><p>"; print '<input type=submit value="Enviar">'; print "</form>"; print '<p></p><div align="center" class="reportSelectTitle">...o puedes mostrar todo:</div><p></p>'; print '<p></p><div align="center">'; print "<p>"; print "</p>"; print '<form action="listvms.cgi" method=post>'; print '<input type="hidden" name="todo" value="si">'; print '<input type=submit value="Mostrar todo">'; print "</form>"; } sub capture_data { # Obtiene la entrada read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); # Divide las variables entre nombre y valor. @pairs = split(/&/, $buffer); # Optiene todas las variables y sus valores (aunque solo hemos pasado uno) foreach $pair (@pairs) { ($name, $value) = split(/=/, $pair); $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FORM{$name} = $value; } return ($FORM{'virtualmachine'}); } sub search_infile { my $chain2search = shift(@_); my $server; my $vmachine; my $status; my $contador=0; my @matched; local $linea; my $data_file="/etc/nagios3/vm_inventory.txt"; open(VMS, $data_file) || die("Could not open file!"); my @raw_data=<VMS>; foreach $linea (@raw_data) { chomp($linea); ($server,$vmachine,$status)=split(/\,/,$linea); if ( $vmachine =~ /($chain2search)/i ) { $matched[$contador] = $linea; $contador++; } } close(VMS); return(@matched); } sub print_results { #Cogemos los par#metros my ($uno)=@_; #desreferenciamos my @matriz=@$uno; # Definimos variables necesarias local $counter = 0; local $style; local $linea; # Pintamos la primera la cabecera de la tabla print '<table border="1" class="status">'; print "<tbody>"; print " <tr>"; print ' <th class="status">Servidor</th><th class="status">Virtual Machine</th><th class="status">Status</th>'; print " </tr>"; foreach $linea (@matriz) { chomp($linea); ($server,$vmachine,$status)=split(/\,/,$linea); if ($counter == 0) { $style = "statusEven"; $counter = 1; } else { $style = "statusOdd"; $counter = 0; } # Ahora que ya tenemos el estilo, pintamos la linea print "<tr class=$style>"; print " <td class=$style>$server</td>"; print " <td class=$style>$vmachine</td>"; print " <td class=$style>$status</td>"; print "</tr>"; } # Cerramos la tabla print "</tbody></table>"; } sub end_html { print "</pre></body></html>"; }
En la función search_infile se especifica el fichero fuente de los datos (en este caso /etc/nagios3/vm_inventory.txt).