#!/usr/bin/env perl # IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html package xCAT_plugin::notification; BEGIN { $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat'; } use lib "$::XCATROOT/lib/perl"; use xCAT::Table; use xCAT::NotifHandler; 1; #------------------------------------------------------------------------------- =head1 xCAT_plugin:notification =head2 Package Description xCAT notification plugini module. This mondule allows users to register and unregister for the xCAT database table changes. =cut #------------------------------------------------------------------------------- #-------------------------------------------------------------------------------- =head3 handled_commands It returns a list of commands handled by this plugin. Arguments: none Returns: a list of commands. =cut #------------------------------------------------------------------------------- sub handled_commands { return { regnotif => "notification", unregnotif => "notification", refnotif => "notification", lsnotif => "notification", enablenotif => "notification", disablenotif => "notification", } } #-------------------------------------------------------------------------------- =head3 process_request It processes the monitoring control commands. Arguments: request -- a hash table which contains the command name. callback -- a callback pointer to return the response to. args -- a list of arguments that come with the command. Returns: 0 for success. The output is returned through the callback pointer. 1. for unsuccess. The error messages are returns through the callback pointer. =cut #------------------------------------------------------------------------------- sub process_request { use Getopt::Long; # options can be bundled up like -vV Getopt::Long::Configure("bundling") ; $Getopt::Long::ignorecase=0; my $request = shift; my $callback = shift; my $command = $request->{command}->[0]; my $args=$request->{arg}; if ($command eq "regnotif") { my ($ret, $msg) = regNotification($args, $callback); if ($msg) { my %rsp=(); $rsp->{dara}->[0]= $msg; $callback->($rsp); } return $ret; } elsif ($command eq "unregnotif") { my ($ret, $msg) = unregNotification($args, $callback); if ($msg) { my %rsp=(); $rsp->{data}->[0]= $msg; $callback->($rsp); } return $ret; } else { my %rsp=(); $rsp->{data}->[0]= "unsupported command: $command."; $callback->($rsp); return 1; } } #-------------------------------------------------------------------------------- =head3 regNotification It registers a notification routine or a command which will be called when there are changes in the data base tables that the routine/command is interested in. Arguments: args - The format of the args is: [-h|--help|-v|--version] or filename tablename[,tablename]... [-o|--operation tableop[,tableop][,tableop]]] where tablename - string. a list of comma seperated names of the tables whose changes will be watched. filename - string. The name of the module (e.g. /usr/lib/xxx.pm) or command (e.g. /usr/bin/xxx) that handles the notification. If it is a perl module, the module must implement the following routine: processTableChanges(action, table_name, old_data, new_data) Refer to notify() subroutine for the meaning of the parameters. If it is a command, the command format should be: command [-d|-a|-u] tablename {[colnames][rowvalues][rowvalues]...} {[colnames][rowvalues]} tableop - it can be 'a' for add, 'd' for delete and 'u' for update. callback - the pointer to the callback function. Returns: none Comments: If the module or the command already exists in the notification table, this subroutine will replace it. =cut #------------------------------------------------------------------------------- sub regNotification { my $args=shift; my $callback=shift; my $VERSION; my $HELP; my $tableops; # subroutine to display the usage sub regnotif_usage { my $callbk=shift; if (! $callbk) { return;} my %rsp; $rsp->{data}->[0]= "Usage:"; $rsp->{data}->[1]= " regnotif filename tablename[,tablename]... [-o|--operation tableop[,tableop][,tableop]]]"; $rsp->{data}->[2]= " where tableop can be 'a' for add, 'd' for delete and 'u' for update"; $rsp->{data}->[3]= " regnotif [-h|--help|-v|--version]"; $callbk->($rsp); } @ARGV=@{$args}; # parse the options if(!GetOptions( 'o|operation=s' => \$tableops, 'h|help' => \$::HELP, 'v|version' => \$::VERSION,)) { ®notif_usage($callback); return; } # display the usage if -h or --help is specified if ($::HELP) { ®notif_usage($callback); return; } # display the version statement if -v or --verison is specified if ($::VERSION) { my %rsp; $rsp->{data}->[0]= "regnotif version 1.0"; if ($callback) { $callback->($rsp); } return; } # must specify the file name and table names if (@ARGV < 2) { ®notif_usage($callback); return; } #table operations must be a,d or u seperated by ',' if ($tableops) { if ($tableops !~ m/^(a|d|u)(,(a|d|u)){0,2}$/) { my %rsp; $rsp->{data}->[0]= "Invalid table operations: $tableops"; if ($callback) { $callback->($rsp); } return; } } else { $tableops="a,d,u"; } my $fname=shift(@ARGV); if ( fname !~ /^\// ) {#relative path $fname = xCAT::Utils->full_path($fname); } my $table_names=shift(@ARGV); my $table=xCAT::Table->new("notification", -create => 1,-autocommit => 0); if ($table) { my %key_col = (filename=>$fname); my %tb_cols=(tables=>$table_names, tableops=>$tableops); $table->setAttribs(\%key_col, \%tb_cols); $table->commit; } #update notification cache xCAT::NotifHandler::sendNotifSignal(); return; } #-------------------------------------------------------------------------------- =head3 unregNotification It unregisters a notification routine or a command. Arguments: args - the format of the ares is: [-h|--help|-v|--version] or filename where filename - string. The name of the module or command that handles the notification. callback - the pointer to the callback funtion. Returns: none =cut #------------------------------------------------------------------------------- sub unregNotification { my $args=shift; my $callback=shift; my $VERSION; my $HELP; # subroutine to display the usage sub unregnotif_usage { my $callbk=shift; if (! $callbk) { return;} my %rsp; $rsp->{data}->[0]= "Usage:"; $rsp->{data}->[1]= " unregnotif filename"; $rsp->{data}->[2]= " unregnotif [-h|--help|-v|--version]"; $callbk->($rsp); } @ARGV=@{$args}; # parse the options if(!GetOptions( 'h|help' => \$::HELP, 'v|version' => \$::VERSION,)) { &unregnotif_usage($callback); return; } # display the usage if -h or --help is specified if ($::HELP) { &unregnotif_usage($callback); return; } # display the version statement if -v or --verison is specified if ($::VERSION) { my %rsp; $rsp->{data}->[0]= "unregnotif version 1.0"; if ($callback) { $callback->($rsp); } return; } # must specify the node range if (@ARGV < 1) { &unregnotif_usage($callback); return; } my $fname=shift(@ARGV); if ( $fname !~ /^\// ) {#relative path $fname = xCAT::Utils->full_path($fname); } my $table=xCAT::Table->new("notification", -create => 1,-autocommit => 0); if ($table) { my %key_col = (filename=>$fname); $table->delEntries(\%key_col); $table->commit; } #update notification cache xCAT::NotifHandler::sendNotifSignal(); return; }