面向IBM Tivoli Monitor 6.1 Universal Agent的Socket解决方案(Perl语言实现)

方案描述:
 该方案是基于ITM UA产品的二次开发过程中的工具包,实现背景是面对ITM产品UA不支持操作系统平台SGI Irix64 6.5操作系统而进行的。由于UA没有直接支持IRIX的agent,因此我们需要通过Universal Agent来进行二次开发。
解决方法:ITM部署有几个层次:
 1、第一个层次;TEPS(Tivoli Enterprice Portal Server)作为一个展现最终系统监控的portal
 2、第二个层次:HUB-TEMS作为一个集中的管理服务器,它管理着多个客户端、agent、remote-TEMS,连接着BI职责的RDBMS、warehouse。
 3、第三个层次:remote-TEMS作为一个远程的管理端可以运用在分布式环境下,并对若干Universal Agent进行管理。
描述对象:
 由于以上第三个层次的部署,所以我们需要考虑如何将Universal Agent不支持的Irix进行信息收集,并通过一定的格式按照UA提供的API,传递执行结果给UA,传递的方式有很多种,比如:套接字、SNMP。这里我们提供的tool kit使用套接字方式。我们可以使用C、C++、Java、Perl。在这里我们使用Perl

 该解决方案种包括一个Perl脚本代码。内有一个file.pm,连同一个日志文件和一个配置文件。
该解决方案基于ITM 6.1 和OMEGAMON XE 产品技术构建而成,它能够工作在Windows, AIX, Solaris, HP/UX, Linux等操作系统平台。

用法:
1、使用UaSocketClient.pm ,你可以理解为这个文件是一个Socket必须的包。
 (1)按照以下的风格和步骤来初始化UaSocketClient
  my $uaClient = new UaSocketClient();
 $uaClient->appl($system);
 $uaClient->host($host);
 $uaClient->port($port);
 $uaClient->locl($locl);
 $uaClient->connect();
 (2)一旦数据已经准备就绪,发送到SOCKET,它将使用$uaClient->send(@data);来调用并通过该数据所在的一个数组。
 (3)在mdl文件种定义每一个数组数据中的元素,你可以以变量形式来创建它,比如你可以使用3个变量来定义Severity, Time, Data

。如:
 Severity D    20                        @ Severity Level of event
 Time            D    20                        @ Time Stamp hh:mm:ss,ccc
 Data        Z   256                        @ Data
2、使用本解决方案
 (1)确保你的UA上的socket data provider已经可以使用
 (2)添加snmp到你的kumenv文件中:KUMA_STARTUP_DP=asfs
 (3)导入一个元数据文件到环境中:CSA_CoreLog.mdl
 (4)编辑CSA_CoreLog.mdl文件中的//SOURCE SOCK localhost,这里以发送数据系统的IP和机器名来编辑。
 (5)把*.mdl文件放到/tmaitm6/metafiles目录。
 (6)导入元数据文件:
  Windows平台, 使用命令行:"kumpcon import *.mdl"
  UNIX平台,使用命令行:"bin/kumpcon import *.mdl"
 (7)编辑本地日志配置文件。
 (8)运行LogMonitor.pl
 (9)一旦UA正常运行,请你自定义并创建你期望的场景的workspaces

 

以下是本解决方案涉及到的5个核心文件:

///////////////////////////////////////////////UaSocketClient.pm ///////////////////////
 package UaSocketClient;
use IO::Socket;
use strict;

#######################################
# Constructor                         #
#######################################
sub new {
 my $proto = shift;
    my $class = ref($proto) || $proto;
 my $this = ();
 $this->{HOST} = undef;
 $this->{PORT} = undef;
 $this->{LOCL} = undef;
 $this->{APPL} = "";
    $this->{SOCK} = undef;
    $this->{STATE} = 'disconnected';
 
 bless ($this, $class);
 return $this;
}

#######################################
# Setter/Getter Methods               #
#######################################
sub host {
 my $this = shift;
 if (@_) { $this->{HOST} = shift }
 return $this->{HOST};
}

#######################################
# Setter/Getter Methods               #
#######################################
sub port {
 my $this = shift;
 if (@_) { $this->{PORT} = shift }
 return $this->{PORT};
}

sub locl {
 my $this = shift;
 if (@_) { $this->{LOCL} = shift }
 return $this->{LOCL};
}

#######################################
# Setter/Getter Methods               #
#######################################
sub appl {
 my $this = shift;
 if (@_) { $this->{APPL} = shift }
 return $this->{APPL};
}

######################################
# Connect to the UA Server           #
######################################
sub connect {
    my $this = shift;

    my $bytesOut = 0;
    while ( ! $bytesOut ) {
        $this->{SOCK} = undef;
        while( ! $this->{SOCK} ) {
            $this->{SOCK} = new IO::Socket::INET(
                PeerAddr  => $this->{HOST},
                PeerPort  => $this->{PORT},
                LocalPort => $this->{LOCL},
                Proto     => 'tcp') or sleep(1);
        }
        $this->{STATE} = 'connected';
        $bytesOut = send( $this->{SOCK}, "$this->{APPL}/n", 0);
    }
    printf "Connected to %s:%s as application %s/n", $this->{HOST}, $this->{PORT}, $this->{APPL};

    return $this->{STATE};
}

#######################################
# Send an event                       #
#######################################
sub send {
 my $this = shift;
    my @lines = @_;
    my $count = 0;
    my $bytesOut = 0;
   
    if ( $this->{STATE} =~ /^connected$/ ) {
        foreach my $line (@lines) {
            if ( $line ) {
                local $SIG{PIPE} = 'IGNORE';
                chomp($line);
                while ( ! send( $this->{SOCK}, "$line/n", 0) ) {
                    print "Reconnecting.../n";
                    $this->connect();
                }
                $count++;
            }
        }
    }
    return $count;
}

#######################################
# Houskeeping                         #
#######################################
sub disconnect {
 my $this = shift;
    syswrite $this->{SOCK}, "//END-DP-INPUT/n";
    close $this->{SOCK};
    $this->{STATE} = 'disconnected';
}

1;

///////////////////////////////////////////////LogMonitor.pl//////////////////////////
#!/usr/bin/perl -w
# LogMonitor.pl
# Monitors the indicated file using the indicated UA Configuration
#----------------
use strict;
use UaSocketClient;
use File;

#--------------------------
# Get Configuration File - See Sample.cfg
#--------------------------
my $configFile = $ARGV[0] || "LogMonitor.cfg";
while ( ! ( $configFile =~ /^/S+/.cfg$/ ) ) {
 print "Please enter the Configuration File (Must end with .cfg): ";
 $configFile = ;
 chomp($configFile);
}

#--------------------------
# Read Configuration
#--------------------------
open (MYFILEIN, $configFile) || die "cannot open $configFile to read: $!/n";
my $line = ;
close (MYFILEIN);
my ($system, $host, $port, $locl, $sleep, $fileName) = split(//s+/, $line);

#--------------------------
# Initilize UA Connection
#--------------------------
my $uaClient = new UaSocketClient();
$uaClient->appl($system);
$uaClient->host($host);
$uaClient->port($port);
$uaClient->locl($locl);
$uaClient->connect();

#--------------------------
# Initilize File to be monitored
#--------------------------
my $file = new File();
$file->name($fileName);

#--------------------------
# Main processing loop
#--------------------------
my $running = 1;
while ( $running ) {
    my @lines = $file->newLines();
    $uaClient->send(@lines);
    print @lines;
    print "===================/n";
    for ( my $i = 0; $i < $sleep && $running; $i++ ) {
        sleep(1);
        open RUNFILE, "LogMonitor.run" or $running = undef;
        close RUNFILE;
    }
}  

#--------------------------
# Houskeeping
#--------------------------
$uaClient->disconnect();
print "done!/n";

/////////////////////////////////////////////LogMonitor.cfg//////////////////

//CSA_CoreLog localhost 7500 25252 5 G:/prod/corelogfiles/core.log

///////////////////////////////////////////File.pm///////////////////////////
package File;
use strict;
use File;

#######################################
# Constructor                         #
#######################################
sub new {
 my $proto = shift;
    my $class = ref($proto) || $proto;
 my $file = ();
 $file->{NAME}   = undef;
 $file->{SIZE}  = 0;
 $file->{FIELDKEY}  = "";
 $file->{RECORDKEY}  = "";
 $file->{MODE}  = "START";
 
 bless ($file, $class);
 return $file;
}

#######################################
# Serialize attributes to string      #
#######################################
sub serialize {
 my $this = shift;
 my $name = sprintf("%-50s",$this->{NAME});
    my $size = sprintf("%-10s",$this->{SIZE});
    my $fkey = sprintf("%-10s",$this->{FIELDKEY});
    my $rkey = sprintf("%-80s",$this->{RECORDKEY});
    my $mode = sprintf("%-10s",$this->{MODE});
    my $string = join('', $name, $size, $fkey, $rkey, $mode);
    return $string;
}

#######################################
# Setter/Getter Methods               #
#######################################
sub name {
 my $this = shift;
 if (@_) {
     $this->{NAME} = shift;
     my $bla;
     ($bla, $bla, $bla, $bla, $bla, $bla, $bla, $this->{SIZE}, $bla ) = stat($this->{NAME});
     if ( ! $this->{SIZE} ) { $this->{SIZE}=0; }
 }
        printf "Monitoring File: %s, Starting Size: %s/n", $this->{NAME}, $this->{SIZE};
 return $this->{NAME};
}

sub size {
 my $this = shift;
 if (@_) { $this->{SIZE} = shift }
 return $this->{SIZE};
}

sub fieldkey {
 my $this = shift;
 if (@_) { $this->{FIELDKEY} = shift }
 return $this->{FIELDKEY};
}

sub recordkey {
 my $this = shift;
 if (@_) { $this->{RECORDKEY} = shift }
 return $this->{RECORDKEY};
}

sub mode {
 my $this = shift;
 if (@_) { $this->{MODE} = shift }
 return $this->{MODE};
}

#######################################
# Get New Records Method              #
#######################################
sub newRecords {
 my $this = shift;
 my @lines = $this->newLines();
 my $newLine;
 my @outLines;
   
 $newLine = '';
 foreach my $line (@lines) {
  chomp($line);
  if ( $line =~ /$this->{RECORDKEY}/ ) {
      if ( ! ( $newLine =~ /^s*$/ )) {
    push @outLines, "$newLine/n";
      }
      $newLine = $line;
  } else {
      if ( ! ( $line =~ /^s*$/ )) {
       $newLine = join($this->{FIELDKEY}, $newLine, $line);
   }
  }
 }
    if ( ! ( $newLine =~ /^s*$/ )) {
  push @outLines, "$newLine/n";
    }
 return @outLines;
}
#######################################
# Get New Lines Method                #
#######################################
sub newLines {
 my $this = shift;
 my $newSize = 0;
 my $bla;
 my @lines;
 ($bla, $bla, $bla, $bla, $bla, $bla, $bla, $newSize, $bla ) = stat($this->{NAME});

 if ( $newSize ) {
  if ( $newSize != $this->{SIZE} ) {
   open (MYFILEIN, $this->{NAME}) || die "cannot open $this->{NAME} to read: $!/n";
   if ( $newSize > $this->{SIZE} ) {
    seek (MYFILEIN, $this->{SIZE}, 0);
   }
   $this->{SIZE} = $newSize;
   @lines = ;
   close (MYFILEIN);
  }
 }
 return @lines;
}


1; 
///////////////////////////////////////////CSA_CoreLog.mdl///////////////
//APPL AAA_Log
//NAME LogData E 1800
//SOURCE SOCK localhost
//ATTRIBUTES
Severity D    20                        @ Severity Level of event
Date            D    20                        @ Date Stamp
Time            D    20                        @ Time Stamp hh:mm:ss,ccc
Thread          D    50                        @ Thread Name
Class           D    50                        @ Class that raised event
EventData       Z   256                        @ Event Data


你可能感兴趣的:(Tivoli)