方案描述:
该方案是基于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文件放到
(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