| perfSONAR_PS-Services-PingER documentation | Contained in the perfSONAR_PS-Services-PingER distribution. |
perfSONAR_PS::Services::MA::PingER - A module that implements MA service.
This module aims to offer simple methods for dealing with requests for information, and the related tasks of intializing the backend storage.
use perfSONAR_PS::Services::MA::PingER;
my %conf = ();
$conf{"METADATA_DB_TYPE"} = "xmldb";
$conf{"METADATA_DB_NAME"} = "/home/netadmin/LHCOPN/perfSONAR-PS/MP/Ping/xmldb";
$conf{"METADATA_DB_FILE"} = "pingerstore.dbxml";
$conf{"SQL_DB_USER"} = "pinger";
$conf{"SQL_DB_PASS"} = "pinger";
$conf{"SQL_DB_DB"} = "pinger_pairs";
my $pingerMA_conf = perfSONAR_PS::SimpleConfig->new( -FILE => 'pingerMA.conf', -PROMPTS => \%CONF_PROMPTS, -DIALOG => '1');
my $config_data = $pingerMA_conf->parse();
$pingerMA_conf->store;
%conf = %{$pingerMA_conf->getNormalizedData()};
my $ma = perfSONAR_PS::MA::PingER->new( \%con );
# or
# $self = perfSONAR_PS::MA::PingER->new;
# $self->setConf(\%conf);
$self->init;
while(1) {
$self->receive;
$self->respond;
}
This API is a work in progress, and still does not reflect the general access needed in an MA. Additional logic is needed to address issues such as different backend storage facilities.
The offered API is simple, but offers the key functions we need in a measurement archive.
create a new instance of the PingER MA
Initiate the MA; configure the configuration defaults, and message handlers.
accessor/mutator for database instance
accessor/mutator for the lookup service
Should the instance of the PingER register with a LS?
register all the metadata that our ma contains to the LS
main access into MA from Daemon Architecture
actually do something the incoming $request message.
messageType: The type of the message where the merging is occurring
eventType: The event type in at least one of the md that caused this handler to be chosen
parentMd: The metadata that was metadataIdRef'd by the childMd
childMd: The metadata that needs to be merged with its parent
perfSONAR_PS::MA::Base, perfSONAR_PS::MA::General, perfSONAR_PS::Common, perfSONAR_PS::Messages, perfSONAR_PS::DB::File, perfSONAR_PS::DB::XMLDB, perfSONAR_PS::DB::RRD, perfSONAR_PS::Datatypes::Namespace, perfSONAR_PS::SimpleConfig
To join the 'perfSONAR-PS' mailing list, please visit:
https://mail.internet2.edu/wws/info/i2-perfsonar
The perfSONAR-PS subversion repository is located at:
https://svn.internet2.edu/svn/perfSONAR-PS
Questions and comments can be directed to the author, or the mailing list.
$Id: PingER.pm 227 2007-06-13 12:25:52Z zurawski $
Yee-Ting Li, <ytl@slac.stanford.edu> Maxim Grigoriev, <maxim@fnal.gov> Jason Zurawski, <zurawski@internet2.edu>
Copyright (C) 2007 by Internet2
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.
| perfSONAR_PS-Services-PingER documentation | Contained in the perfSONAR_PS-Services-PingER distribution. |
package perfSONAR_PS::Services::MA::PingER; use version; our $VERSION = 0.09;
use perfSONAR_PS::Common; use perfSONAR_PS::Messages; use perfSONAR_PS::Client::LS::Remote; use perfSONAR_PS::Services::MA::General; use perfSONAR_PS::Datatypes::Namespace; use perfSONAR_PS::Datatypes::EventTypes; use perfSONAR_PS::Datatypes::v2_0::nmwg::Message; use perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Data; use perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Metadata; use perfSONAR_PS::Datatypes::Message; use perfSONAR_PS::Datatypes::PingER; use perfSONAR_PS::DB::SQL::PingER; use perfSONAR_PS::ParameterValidation; use perfSONAR_PS::Services::Base; use base 'perfSONAR_PS::Services::Base'; use Data::Dumper; use fields qw( DATABASE LS_CLIENT eventTypes); use warnings; use Exporter; use Params::Validate qw(:all); use POSIX qw(strftime); use constant CLASSPATH => 'perfSONAR_PS::Services::MA::PingER'; use Log::Log4perl qw(get_logger); our $logger = get_logger( CLASSPATH ); # name of configuraiotn elements to pick up our $basename = 'pingerma'; our $processName = 'perfSONAR-PS PingER MA';
sub new { my $package = shift; my $self = $package->SUPER::new( @_ ); $self->{'DATABASE'} = undef; $self->{'LS_CLIENT'} = undef; $self->{eventTypes} = perfSONAR_PS::Datatypes::EventTypes->new(); return $self; }
sub init { my ($self, $handler) = @_; eval { # info about service $self->configureConf( 'service_name', $processName, $self->getConf('service_name') ); $self->configureConf( 'service_type', 'MA', $self->getConf('service_type') ); $self->configureConf( 'service_description', $processName . ' Service', $self->getConf('service_description') ); $self->configureConf( 'service_accesspoint', 'http://localhost:'.$self->{PORT}."/".$self->{ENDPOINT} , $self->getConf('service_accesspoint') ); $self->configureConf( 'db_host', undef, $self->getConf('db_host') ); $self->configureConf( 'db_port', undef, $self->getConf('db_port') ); $self->configureConf( 'db_type', 'SQLite', $self->getConf('db_type') ); $self->configureConf( 'db_name', 'pingerMA.sqlite3', $self->getConf('db_name') ); $self->configureConf( 'db_username', undef, $self->getConf( 'db_username') ); $self->configureConf( 'db_password', undef, $self->getConf( 'db_password') ); # other $self->configureConf( 'query_size_limit', undef, $self->getConf('query_size_limit') ); # ls stuff $self->configureConf( 'enable_registration', undef, $self->getConf( 'enable_registration') ); }; if ( $@ ) { $logger->error( "Configuration incorrect: $@" ); return -1; } $logger->info( "Initialising PingER MA"); if ( $handler ) { $logger->debug("Setting up message handlers"); $handler->registerEventHandler("SetupDataRequest", $self->{eventTypes}->tools->pinger, $self); $handler->registerEventHandler("MetadataKeyRequest", $self->{eventTypes}->tools->pinger, $self); $handler->registerEventHandler("SetupDataRequest", $self->{eventTypes}->ops->select, $self); $handler->registerEventHandler("MetadataKeyRequest", $self->{eventTypes}->ops->select, $self); my @eventTypes = ( $self->{eventTypes}->tools->pinger, $self->{eventTypes}->ops->select ); $handler->registerMergeHandler("MetadataKeyRequest", \@eventTypes, $self); $handler->registerMergeHandler("SetupDataRequest", \@eventTypes, $self); } # setup database $logger->debug( "initializing database " . $self->getConf("db_type") ); if( $self->getConf("db_type") eq "SQLite" || "mysql") { # setup DB object eval { my $dbo = perfSONAR_PS::DB::SQL::PingER->new( { driver => $self->getConf( "db_type" ), database => $self->getConf( "db_name" ), host => $self->getConf( "db_host"), port => $self->getConf( "db_port"), username => $self->getConf( "db_username" ), password => $self->getConf( "db_password" ), }); if($dbo->openDB() == 0 ) { $self->database( $dbo ); } else { die " Failed to open DB" . $dbo->ERRORMSG; } }; if ( $@ ) { $logger->logdie( "Could not open database '" . $self->getConf( 'db_type') . "' for '" . $self->getConf( 'db_name') . "' using '" . $self->getConf( 'db_username') ."'" . $@); } } else { $logger->logdie( "Database type '" . $self->getConf("db_type") . "' is not supported."); return -1; } # set name $0 = $processName; return 0; }
sub database { my $self = shift; if ( @_ ) { $self->{DATABASE} = shift; } return $self->{DATABASE}; } sub configureConf { my $self = shift; my $key = shift; my $default = shift; my $value = shift; my $fatal = shift; # if set, then if there is no value, will return -1 if ( defined $value ) { if ( $value =~ /^ARRAY/ ) { my $index = scalar @$value - 1; #$logger->info( "VALUE: $value, SIZE: $index"); $value = $value->[$index]; $logger->fatal( "Value for '$key' set to '$value'"); } $self->{CONF}->{$basename}->{$key} = $value; } else { if ( ! $fatal ) { if ( defined $default ) { $self->{CONF}->{$basename}->{$key} = $default; $logger->warn( "Setting '$key' to '$default'"); } else { $self->{CONF}->{$basename}->{$key} = undef; $logger->warn( "Setting '$key' to null"); } } else { $logger->logdie( "Value for '$key' is not set" ); } } return 0; } sub getConf { my $self = shift; my $key = shift; return $self->{'CONF'}->{$basename}->{$key}; }
sub ls { my $self = shift; if ( @_ ) { $self->{'LS_CLIENT'} = shift; } return $self->{'LS_CLIENT'}; }
sub needLS($) { my ($self) = @_; return $self->getConf( 'enable_registration' );; }
sub registerLS($) { my $self = shift; $0 = $processName . ' LS Registration'; $logger->info( "Registering PingER MA with LS"); # create new client if required if ( ! defined $self->ls() ) { my $ls_conf = { 'SERVICE_TYPE' => $self->getConf( 'service_type' ), 'SERVICE_NAME' => $self->getConf( 'service_name'), 'SERVICE_DESCRIPTION' => $self->getConf( 'service_description'), 'SERVICE_ACCESSPOINT' => $self->getConf( 'service_accesspoint' ), }; my $ls = new perfSONAR_PS::Client::LS::Remote( $self->getConf('ls_instance'), $ls_conf, ); $self->ls( $ls ); } my @sendToLS = (); # open db my $iterator = perfSONAR_PS::DB::PingER_DB::MetaData::Manager->get_metaData_iterator(); while( $md = $iterator->next ) { # get hosts my $endpoint = perfSONAR_PS::Datatypes::v2_0::nmwgt::Message::Metadata::Subject::EndPointPair->new(); my $src = perfSONAR_PS::Datatypes::v2_0::nmwgt::Message::Metadata::Subject::EndPointPair::Src->new({ 'value' => $md->ip_name_src(), 'type' => 'hostname', }); my $dst = perfSONAR_PS::Datatypes::v2_0::nmwgt::Message::Metadata::Subject::EndPointPair::Src->new({ 'value' => $md->ip_name_dst(), 'type' => 'hostname', }); $endpoint->src( $src ); $endpoint->dst( $dst ); my $subject = perfSONAR_PS::Datatypes::v2_0::pinger::Message::Metadata::Subject->new(); $subject->endPointPair( $endpoint ); # setup parameters my @params = (); no strict 'refs'; foreach my $p ( qw/ count packetSize interval ttl / ) { my $param = perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Metadata::Parameters::Parameter->new({ 'name' => $p, }); my $q = $p; $q = 'packetInterval' if $p eq 'interval'; $param->text( $md->$q() ); push @params, $param; } use strict 'refs'; my $parameters = perfSONAR_PS::Datatypes::v2_0::pinger::Message::Metadata::Parameters->new(); $parameters->parameter( @params ); # event type my $eventType = perfSONAR_PS::Datatypes::EventTypes->new(); # create the metadata my $mdid = ref($md->metaID) eq 'Math::BigInt' ? $md->metaID->bstr : $md->metaID; my $metadata = perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Metadata->new({ 'id' => $mdid }); $metadata->subject( $subject ); $metadata->eventType( $eventType->tools->pinger ); $metadata->parameters( $parameters ); push @sendToLS, $metadata->getDOM()->toString() ; } # foreach my $meta ( @sendToLS ) { # $logger->debug( "Found metadata for LS registration: '" . $meta . "'" ); # } return $self->ls()->registerStatic(\@sendToLS); } sub handleMessageBegin($$$$$$$$) { my ($self, $ret_message, $messageId, $messageType, $msgParams, $request, $retMessageType, $retMessageNamespaces); $0 = $processName . ' Query'; return 1; } sub handleMessageEnd($$$) { my ($self, $ret_message, $messageId); return 1; }
sub handleEvent() { my ($self, @args) = @_; my $parameters = validateParams(@args, { output => 1, messageId => 1, messageType => 1, messageParameters => 1, eventType => 1, subject => 1, filterChain => 1, data => 1, rawRequest => 1, doOutputMetadata => 1, }); # shoudl do some validation on the eventType ${ $parameters->{"doOutputMetadata"} } = 0; my $response = $self->__handleEvent( $parameters->{"messageType"}, $parameters->{"rawRequest"}, \@{ $parameters->{"subject"}}, $parameters->{"data"}, $parameters->{"filterChain"}->[0] , $parameters->{"messageParameters"} ); ##### $response is foreach my $element (@{$response->metadata}, @{$response->data}) { $parameters->{"output"}->addExistingXMLElement( $element->getDOM()); } return ; }
sub __handleEvent { my( $self, $messageType, $raw_request, $mds, $data, $filters, $message_parameters ) = @_; $logger->debug( "\n\n\nRequest:\n" . Dumper $raw_request ); $logger->debug( " Type= $messageType md = " . $mds->[0]->toString . " Data=" . $data->toString . " filters= " . (Dumper $filters) . " mparams= " . (Dumper $message_parameters ) ); my $doc = $raw_request->getRequestDOM(); $logger->info( "\n\nDOM:\n" . $doc->toString ); my $arr_filters = []; if($filters && ref($filters) eq 'ARRAY') { foreach my $filter (@{$filters}) { $logger->debug( " Filter .... " . $filter->toString); push @{$arr_filters}, perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Metadata->new( $filter ); } } $logger->info("Unmarshalling into PingER object"); my $pingerRequest = perfSONAR_PS::Datatypes::PingER->new( {metadata => [perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Metadata->new($mds->[0])], data => [perfSONAR_PS::Datatypes::v2_0::nmwg::Message::Data->new($data)], filters => $arr_filters}); my $error_msg = ''; my $type = $messageType; my $messageIdReturn = "message." . perfSONAR_PS::Common::genuid(); (my $responseType = $type ) =~ s/Request/Response/; $logger->debug("Parsing request...Registering namespaces..."); $pingerRequest->registerNamespaces(); $logger->debug("Done..."); ### pass db handler down request object $logger->debug("Creating PingER response"); my $pingerResponse = perfSONAR_PS::Datatypes::Message->new( {type => $responseType , id => $messageIdReturn }); # response message $logger->debug("Done..."); # foreach my $field ($pingerResponse->show_fields('Public')) { # $logger->debug("Pinger Response: $field= " . $pingerResponse->{$field}); # } #### map namespaces on response $logger->debug(" Mapping namespaces on response"); $pingerResponse->nsmap($pingerRequest->nsmap); ## merge chains and work with them in request $logger->debug("Done..."); ### my $evt = $pingerRequest->eventTypes; ## setting up db object $pingerRequest->DBO($self->database); my $errorMessage = $pingerRequest->handle($type, $pingerResponse, $self->{'CONF'}->{'pingerma'}); $logger->debug( "PINGER RESPONSE: $errorMessage\n" . $pingerResponse->asString() ); return $pingerResponse; }
sub mergeMetadata { my ($self, @args) = @_; my $parameters = validateParams(@args, { messageType => 1, eventType => 1, parentMd => 1, childMd => 1, }); my $parent_md = $parameters->{parentMd}; my $child_md = $parameters->{childMd}; $logger->debug("mergeMetadata called"); # Just use the default merge routine for now defaultMergeMetadata($parent_md, $child_md); return; } 1;