Blog de Javier Castañón – JavCastaPosts RSS Comments RSS


Nuevo Post: Cisco Centinel – Utilidad en C# y Perl para monitorizar un dispositivo Cisco http://t.co/jUJ04xlr
@javcasta
Javier Castañón

Referencia:

http://www.javcasta.com/2012/09/24/networking-cisco-perl-scripting-con-modulo-net-telnet-cisco/

Descargar:

Requisitos:

  • En maquina cliente:
    • - Framework .Net 3.5 o 4 instalado
    • - Perl (ActivePerl) instalado
    • - Modulo de Perl Telnet-Cisco (ver referencia)
    • Y si deseas que se puedan enviar alertas por mail:  Modulo de Perl Email-Send-Gmail (ppm install Email-Send-Gmail)
  • En dispositivo Cisco a monitorizar:
    • - ICMP habilitado tal que conteste (a un ping) con un icmp echo-reply ante un icmp echo-request.
    • - Acceso vía telnet si se desea usar las opciones de:
      • – % CPU del dispositivo
      • – ICMP: ping desde el dispositivo a un host

Esta utilidad la he implementado bajo C# 4.0 y desarrollado en sharpDevelop 4.2, compilada para .Net 3.5 client profile.
C# lo he usado para la GUI o el interfaz gráfico de usuario y la opción de enviar un ping al dispositivo a monitorizar.
Para obtener, vía telnet, el % de utilización de la CPU y efectuar un ping desde el dispositivo a otro host, he usado scripts en Perl con el módulo Telnet-Cisco y el módulo Email-Send-Gmail.

La mecánica de la utilidad es la siguiente.

En el grupo parámetros:
Hostname o IP: Se debe de poner el nombre o ip del dispositivo Cisco a monitorizar.
Intervalo: El tiempo x en segundos del delay o retardo del bucle de monitorización.

En el grupo Monitorizar:
Elegimos mediante los checkBox los métodos de monitorización:
1- Ping desde nuestro host al dispositivo a monitorizar (pudiendo variarse el timeout del ping en un textBox)
2- Mostrar el % de uso de la CPU del dispositivo a monitorizar
3- Ping desde el dispositivo a monitorizar a un host
(la utilidad presenta en el comboBox nuestras IPs como destino del ping desde el dispositivo, pudiendose elegir una de estas o editar la que deseemos)

Los campos usuario y clave, obviamente son para acceder vía telnet al dispositivo a monitorizar
(sin tener acceso vía telnet los métodos 2 y 3 no surtirán efecto).

Tras tener parametrizada la utilidad, se comenzaria el bucle de monitorización cada x sg clikando en
el botón comenzar monitorización. Para parar, se clikaria el boton stop.

En el richTextBox veremos el estado del dispositivo y el ciclo (cuantas veces cada x sg se han efectuado los métodos de monitorización)
Tambien veremos una imagen con 3 estados:

  • ? = indeterminado (no se ha empezado a monitorizar o se ha clikado el boton stop)
  • OK = El dispositivo responde correctamente a los métodos de monitorización
  • !!! = El dispositivo no responde correctamente a los métodos de monitorización.

Si se da este último caso y el ciclo es >= a 2 y esta marcado el checkBox de enviar alerta vía e-mail:
Se enviará un correo electrónico desde una cuenta de gmail (hay que parametrizar la cuenta y la clave)
 a la dirección de correo definida en el textBox, conteniendo los datos de la alerta.
Para ello es condicion necesaria tener instalado el módulo de perl Email-Send-Gmail (http://search.cpan.org/dist/Email-Send-Gmail-0.33/)

El código de los scripts en perl

cisco-telnet.pl

local $| = 1;
  use Net::Telnet::Cisco;
  # JavCasta - http://javcasta.com/ - 2.012
  my $device = $ARGV[0];
  my $usuario = $ARGV[1];
  my $clave = $ARGV[2];
  my $pinghost = $ARGV[3];
  my $cpu = $ARGV[4];
  
  eval {
	my $session = Net::Telnet::Cisco->new(Host => $device);
	$session->login($usuario, $clave);
  
	# Execute a command
	my $comando = 'ping '.$pinghost;
	my @output = $session->cmd($comando);
	print @output;
	my $compara = 'CPU';
    if ( $cpu eq $compara ) {
		my @output2 = $session->cmd('show processes cpu | include CPU');
		print @output2;
		print 'fin'; #añado fin para tratamiento de cadenas desde c#
    }
  
    $session->close;
  };
    if ( $@ ) {
     my @output = "Error: $@";
     print @output;
  }

send-mail.pl

local $| = 1;
use strict;
  use warnings;
  use Email::Send;
  use Email::Send::Gmail;
  use Email::Simple::Creator;
  
  my $miFrom = $ARGV[0];
  my $miTo = $ARGV[1];
  my $miSubject = $ARGV[2];
  my $miBody = $ARGV[3];
  my $miClave = $ARGV[4];
  
  my $email = Email::Simple->create(
      header => [
          From    => $miFrom,
          To      => $miTo,
          Subject => $miSubject,
      ],
      body => $miBody,
  );

  my $sender = Email::Send->new(
      {   mailer      => 'Gmail',
          mailer_args => [
              username => $miFrom,
              password => $miClave,
          ]
      }
  );
  eval { $sender->send($email) };
  #die "Error enviando email: $@" if $@;
  if ( $@ ) {
    my @output = "Error_envio_alerta: $@";
    print @output;
    }

El código del mainform.cs de la aplicación en C#:

/*
 * Created by SharpDevelop.
 * User: JavCasta - http://javcasta.com/
 * Date: 24/09/2012
 * Time: 10:26
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Management;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Mail;

namespace CiscoCentinel
{
	/// <summary>
	/// Description of MainForm.
	/// </summary>
	public partial class MainForm : Form
	{
		ManagementClass objMC;
		ManagementObjectCollection objMOC;
		string[] ipaddresses;
		int i = 0;
		bool continuar = true;
		int ciclo = 0;
		string comando = "";
		bool enviar = false;
		string cuerpo1, cuerpo2, cuerpo3 ="";
		
		public MainForm()
		{
			//
			// The InitializeComponent() call is required for Windows Forms designer support.
			//
			InitializeComponent();
			
			//
			// TODO: Add constructor code after the InitializeComponent() call.
			//
			misips();

		}
		//ref: run a perl script from c#
		//http://social.msdn.microsoft.com/Forums/zh/csharpgeneral/thread/ea9455e1-b254-49e1-99df-41718ea80b5b
		
		void Button1Click(object sender, EventArgs e)
		{
			//Comenzamos a monitorizar
			richTextBox1.Text = "";
			progressBar1.Style = ProgressBarStyle.Marquee;
			//Bucle cada intervalo
			while (continuar) {
				progressBar1.Style = ProgressBarStyle.Marquee;
				ciclo++;
				enviar = false;
				groupBox3.Text="Estado - ciclo: " + ciclo.ToString();
				//si icmp ping al -> ping al router
				if (checkBox1.Checked) {
					if (miPing(textBox1.Text)) {
						//MessageBox.Show("OK");
						richTextBox1.Text += (DateTime.Now).ToString()+": Ping al dispositivo " + textBox1.Text + " OK!!!" + "\r\n";
						richTextBox1.SelectionStart = richTextBox1.Text.Length;
						pictureBox1.Visible = false;
						pictureBox2.Visible = true;
						pictureBox3.Visible = false;
					}
					else
					{
						richTextBox1.Text += (DateTime.Now).ToString()+": Ping al dispositivo " + textBox1.Text + " NO OK!!!" + "\r\n";
						richTextBox1.SelectionStart = richTextBox1.Text.Length;
						pictureBox1.Visible = false;
						pictureBox2.Visible = false;
						pictureBox3.Visible = true;
						//if (ciclo >= 2) enviamail() con alerta dispositivo no responde a ping
						if ( ciclo > 1 ) {
							cuerpo1 = (DateTime.Now).ToString()+": Ping al dispositivo "+textBox1.Text+" NO OK!!!\r\n";
							enviar = true;
						}
					} //else
							
					}
				
				//si icmp ping desde el dispositivo al host
				if (checkBox3.Checked) {
					comando = "cisco-telnet.pl" + " " + '"' +textBox1.Text +'"' + " " +'"'+ textBox2.Text+'"' + " " + '"'+textBox3.Text+'"' + " " + '"'+ comboBox1.Text+'"';
					if (checkBox2.Checked) comando += " " + '"'+"CPU"+'"';
					if (!checkBox2.Checked) comando += " " + '"'+"foo"+'"';
					Cursor.Current = Cursors.WaitCursor;
					elproceso();
					
				}
				//enviar
				string cuerpo = '"'+ cuerpo1 + cuerpo2 + cuerpo3 +'"';
				enviaAlerta("send-mail.pl"+" "+'"'+textBox8.Text+'"'+" "+'"'+textBox4.Text+'"'+" "+'"'+"Alerta"+'"'+" "+cuerpo+" "+'"'+textBox7.Text+'"');
				enviar = false;
				//delay
				Sleep(int.Parse(textBox5.Text));
			} //while
			continuar = true;
			
		}
		
		static void Sleep(int sg)
        {
            //http://forums.devshed.com/showpost.php?p=1621059&postcount=6
			DateTime dt1 = DateTime.Now;
            int diff = 0;

            while (diff < sg)
            {
                DateTime dt2 = DateTime.Now;
                TimeSpan ts = dt2.Subtract(dt1);
                diff = (int)ts.TotalSeconds;
                Application.DoEvents();

            }
        }
		
		public void elproceso()
		{
			try {
			ProcessStartInfo perlStartInfo = new ProcessStartInfo(@"perl.exe");
			//MessageBox.Show(comando);
			perlStartInfo.Arguments = comando;
            perlStartInfo.UseShellExecute = false;
            perlStartInfo.WindowStyle = ProcessWindowStyle.Minimized;
            perlStartInfo.RedirectStandardOutput = true;
            perlStartInfo.RedirectStandardError = true;
            perlStartInfo.CreateNoWindow = false;

            Process perl = new Process();
            perl.StartInfo = perlStartInfo;
            
            perl.Start();
            string output = perl.StandardOutput.ReadToEnd();
            perl.WaitForExit(5000);
            if (output.Contains("CPU"))
			{
			    int first = output.IndexOf("CPU");
        		int last = output.LastIndexOf("fin");
        		string str2 = output.Substring(first, last - first);
            	richTextBox1.Text += str2 + "\r\n";
			    
			}
            //si Success rate is 80 o 100 percent ok, si no no ok
            if (output.Contains("Success rate is 80") || output.Contains("Success rate is 100")) 
            {
            	richTextBox1.Text += (DateTime.Now).ToString()+": Ping desde el dispositivo " + textBox1.Text + " al host " + comboBox1.Text + " OK!!!" + "\r\n";
            	pictureBox1.Visible = false;
				pictureBox2.Visible = true;
				pictureBox3.Visible = false;
				enviar = false;
            } 
            else
            {	
            	if (output.Contains("Success rate"))
            	{
            		richTextBox1.Text += (DateTime.Now).ToString()+": Ping desde el dispositivo " + textBox1.Text + " al host " + comboBox1.Text + " NO OK!!!" + "\r\n";	
            		richTextBox1.SelectionStart = richTextBox1.Text.Length;
            		pictureBox1.Visible = false;
					pictureBox2.Visible = false;
					pictureBox3.Visible = true;
					if (ciclo > 1) 
					{
						cuerpo2 = (DateTime.Now).ToString()+": Ping desde el dispositivo "+textBox1.Text+" al host "+comboBox1.Text+" (respuesta <= del 60%) NO OK!!!\r\n";
						enviar = true;					
					}
            	}
            	else 
            	{
            		if (output.Contains("Error:")) 
            		{
            			richTextBox1.Text += (DateTime.Now).ToString()+ ": No hay conexion al dispositivo " + textBox1.Text + " via telnet!!!" + "\r\n";
            			if (ciclo > 1) 
            			{
            				cuerpo3 = (DateTime.Now).ToString()+": No hay conexion al dispositivo "+ textBox1.Text+" via telnet \r\n";
            				enviar = true;
            			}
           			}
            	}
            }
            
            } //try
            catch (Exception ex) {
            	richTextBox1.Text += ex.ToString() + "\r\n";
            }
			Cursor.Current = Cursors.Default;
		}
		
		public void misips()
		{
			
			objMC = new ManagementClass("Win32_NetworkAdapterConfiguration");
            objMOC = objMC.GetInstances();
 			i=0;
			foreach(ManagementObject objMO in objMOC) 
			{
          		if(!(bool)objMO["ipEnabled"]) 
                	 continue; 
       			i=i+1; // i = nº de NICs
       			ipaddresses = (string[]) objMO["IPAddress"];
       			 if (ipaddresses != null) {
                    foreach(string sIP in ipaddresses) {
       					comboBox1.Text=sIP;
                        comboBox1.Items.Add(sIP);
                    }
                }
			}
		}
		
		public bool miPing(string mihost)
		{
		
			Ping p = new Ping();
			int myTimeOut = int.Parse(textBox6.Text);
			bool result = false;
        	try
        	{
            	PingReply reply = p.Send(mihost, myTimeOut);
            	if (reply.Status == IPStatus.Success)
            	  return true;
        	}
        	catch { }
        	return result;
		
		}
		
		void Button2Click(object sender, EventArgs e)
		{
			//stop
			progressBar1.Style = ProgressBarStyle.Blocks;
			continuar = false;
			
			Process[] prs = Process.GetProcesses();
			foreach (Process pr in prs)
			{
				if (pr.ProcessName == "perl")
				{
					pr.Kill();
				}
			}
			pictureBox1.Visible = true;
			pictureBox2.Visible = false;
			pictureBox3.Visible = false;
			
		}
		
		void Button3Click(object sender, EventArgs e)
		{
			Process.Start("http://javcasta.com");
		}
		
		// send alerta por email
		public void enviaAlerta(string comando) 
		{
			if (enviar) try {
			ProcessStartInfo perlStartInfo = new ProcessStartInfo(@"perl.exe");
			perlStartInfo.Arguments = comando;
            perlStartInfo.UseShellExecute = false;
            perlStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            perlStartInfo.RedirectStandardOutput = true;
            perlStartInfo.RedirectStandardError = true;
            perlStartInfo.CreateNoWindow = false;

            Process perl = new Process();
            perl.StartInfo = perlStartInfo;
            
            perl.Start();
            string output = perl.StandardOutput.ReadToEnd();
            perl.WaitForExit(10000);
            if (output.Contains("Error_envio_alerta")) richTextBox1.Text += output +"\r\n";
            else richTextBox1.Text += "Enviada alerta por email";
			} catch {}
		
		}
	}
}

Y voila :-)

Share
Clika en el altavoz para oir el postAltavoz


One Response to “Cisco Centinel – Utilidad en C# y Perl para monitorizar un dispositivo Cisco”

  1. [...] Idea Origen de la utilidad: Cisco Centinel – Utilidad en C# y Perl para monitorizar un disposi… [...]

Leave a Reply

Los enlaces en los comentarios pueden encontrarse libres de nofollow.

?>