| perfSONAR_PS-Client-LS-Remote documentation | view source | Contained in the perfSONAR_PS-Client-LS-Remote distribution. |
perfSONAR_PS::Client::LS::Remote - A module that provides a client API for an LS
This module aims to offer simple methods for dealing with requests for information, and the related tasks of interacting with backend storage.
use perfSONAR_PS::Client::LS::Remote;
my %conf = ();
$conf{"SERVICE_ACCESSPOINT"} = "http://someorganization.org:8080/perfSONAR_PS/services/service";
$conf{"SERVICE_NAME"} = "Some Organization's Service MA"
$conf{"SERVICE_TYPE"} = "MA"
$conf{"SERVICE_DESCRIPTION"} = "Service MA"
my $ls = "http://someorganization.org:8080/perfSONAR_PS/services/LS";
my $ls_client = perfSONAR_PS::Client::LS::Remote->new($ls, \%conf, \%ns);
# or
# $ls_client = perfSONAR_PS::Client::LS::Remote->new;
# $ls_client->setURI($ls);
# $ls_client->setConf(\%conf);
# $ls_client->setNamespaces(\%ns);
$ls_client->registerStatic(\@data);
$ls_client->sendKeepalive($conf{"SERVICE_ACCESSPOINT"});
$ls_client->sendDeregister($conf{"SERVICE_ACCESSPOINT"});
my $ls2 = "http://otherorganization.org:8080/perfSONAR_PS/services/LS";
my $ls_client2 = perfSONAR_PS::Client::LS::Remote->new($ls2);
my %queries = ();
$queries{"req1"} = "";
$queries{"req1"} .= "declare namespace nmwg=\"http://ggf.org/ns/nmwg/base/2.0/\";\n";
$queries{"req1"} .= "for \$data in /nmwg:store/nmwg:data\n";
$queries{"req1"} .= " let \$metadata_id := \$data/\@metadataIdRef\n";
$queries{"req1"} .= " where \$data//*:link[\@id=\"link1\"] and \$data//nmwg:eventType[text()=\"http://ggf.org/ns/nmwg/characteristic/link/status/20070809\"]\n";
$queries{"req1"} .= " return /nmwg:store/nmwg:metadata[\@id=\$metadata_id]\n";
$queries{"req2"} = "";
$queries{"req2"} .= "declare namespace nmwg=\"http://ggf.org/ns/nmwg/base/2.0/\";\n";
$queries{"req2"} .= "for \$data in /nmwg:store/nmwg:data\n";
$queries{"req2"} .= " let \$metadata_id := \$data/\@metadataIdRef\n";
$queries{"req2"} .= " where \$data//*:link[\@id=\"link2\"] and \$data//nmwg:eventType[text()=\"http://ggf.org/ns/nmwg/characteristic/link/status/20070809\"]\n";
$queries{"req2"} .= " return /nmwg:store/nmwg:metadata[\@id=\$metadata_id]\n";
my ($status, $res) = $ls_client2->query(\%queries);
if ($status != 0 or not defined $res{"req1"} or not defined $res{"req2"}) {
print "Error: querying $ls2 failed\n";
exit(-1);
}
my ($query_status, $query_res);
($query_status, $query_res) = $res{"req1"};
if ($query_status != 0) {
print "Couldn't get information on query req1: ".$query_res."\n";
exit(-1);
} else {
print "Results for res1: ".$query_res->toString()."\n";
}
($query_status, $query_res) = $res{"req2"};
if ($query_status != 0) {
print "Couldn't get information on query req2: ".$query_res."\n";
exit(-1);
} else {
print "Results for res1: ".$query_res->toString()."\n";
}
The offered API is simple, but offers the key functions we need in a measurement archive.
The parameters are the URI of the Lookup Service, a %conf describing the service for registration purposes.
The %conf can have 4 keys in it:
SERVICE_NAME - The name of the service registering data SERVICE_ACCESSPOINT - The URL for the service registering data SERVICE_TYPE - The type (MA, LS, etc) of the service registering data SERVICE_DESCRIPTION - A description of the service registering data
sub setURI { my ($self, $uri) = @_; my $logger = get_logger("perfSONAR_PS::Client::LS::Remote");
if(defined $uri and $uri ne "") {
$self->{URI} = $uri;
}
else {
$logger->error("Missing argument.");
}
return;
}
if(defined $conf and $conf ne "") {
$self->{CONF} = \%{$conf};
}
else {
$logger->error("Missing argument.");
}
return;
}
if (not defined $self->{URI}) {
return -1;
}
my ($host, $port, $endpoint) = &perfSONAR_PS::Transport::splitURI($self->{URI});
if (not defined $host and not defined $port and not defined $endpoint) {
return -1;
}
my $sender = new perfSONAR_PS::Transport($host, $port, $endpoint);
my $doc = perfSONAR_PS::XML::Document_string->new();
startMessage($doc, "message.".genuid(), "", "LSDeregisterRequest", "", {perfsonar=>"http://ggf.org/ns/nmwg/tools/org/perfsonar/1.0/", psservice=>"http://ggf.org/ns/nmwg/tools/org/perfsonar/service/1.0/"});
my $mdID = "metadata.".genuid();
createMetadata($doc, $mdID, "", createKey($self, $key), undef);
createData($doc, "data.".genuid(), $mdID, "", undef);
endMessage($doc);
return callLS($self, $sender, $doc->getValue());
}
if (not defined $self->{URI}) {
return -1;
}
my ($host, $port, $endpoint) = &perfSONAR_PS::Transport::splitURI($self->{URI});
if (not defined $host and not defined $port and not defined $endpoint) {
return -1;
}
my $sender = new perfSONAR_PS::Transport($host, $port, $endpoint);
my $doc = perfSONAR_PS::XML::Document_string->new();
startMessage($doc, "message.".genuid(), "", "LSKeepaliveRequest", "", {perfsonar=>"http://ggf.org/ns/nmwg/tools/org/perfsonar/1.0/", psservice=>"http://ggf.org/ns/nmwg/tools/org/perfsonar/service/1.0/"});
my $mdID = "metadata.".genuid();
createMetadata($doc, $mdID, "", createKey($self, $key), undef);
createData($doc, "data.".genuid(), $mdID, "", undef);
endMessage($doc);
return callLS($self, $sender, $doc->getValue());
}
if (not defined $self->{URI}) {
return -1;
}
if(!$self->{ALIVE}) {
my $echo_service = perfSONAR_PS::Client::Echo->new($self->{URI});
my ($status, $res) = $echo_service->ping();
if ($status == -1) {
$logger->error("Ping to ".$self->{URI}." failed: $res");
return -1;
}
$self->{ALIVE} = 1;
}
if($self->{FIRST}) {
if ($self->sendDeregister($self->{CONF}->{"SERVICE_ACCESSPOINT"}) == 0) {
$logger->debug("Nothing registered.");
}
else {
$logger->debug("Removed old registration.");
}
my @resultsString = ();
@resultsString = @{$data_ref};
if($#resultsString != -1) {
my ($status, $res) = $self->__register(createService($self), $data_ref);
if ($status == -1) {
$logger->error("Unable to register data with LS.");
$self->{ALIVE} = 0;
}
}
}
else {
if ($self->sendKeepalive() == -1) {
my @resultsString = ();
@resultsString = @{$data_ref};
if($#resultsString != -1) {
my ($status, $res) = $self->__register(createService($self), $data_ref);
if ($status == -1) {
$logger->error("Unable to register data with LS.");
$self->{ALIVE} = 0;
return -1;
}
}
}
}
$self->{FIRST} = 0 if $self->{FIRST};
return 0;
}
if (not defined $self->{URI}) {
return -1
}
my ($host, $port, $endpoint) = &perfSONAR_PS::Transport::splitURI($self->{URI});
if (not defined $host and not defined $port and not defined $endpoint) {
return -1
}
my $sender = new perfSONAR_PS::Transport($host, $port, $endpoint);
my @data = @{ $data_ref };
my $iterations = int((($#data+1)/$self->{CHUNK}));
my $x = 0;
for(my $y = 1; $y <= ($iterations+1); $y++) {
my $doc = perfSONAR_PS::XML::Document_string->new();
startMessage($doc, "message.".genuid(), "", "LSRegisterRequest", "", {perfsonar=>"http://ggf.org/ns/nmwg/tools/org/perfsonar/1.0/", psservice=>"http://ggf.org/ns/nmwg/tools/org/perfsonar/service/1.0/"});
my $mdID = "metadata.".genuid();
createMetadata($doc, $mdID, "", createService($self), undef);
for(; $x < ($y*$self->{CHUNK}) and $x <= $#data; $x++) {
createData($doc, "data.".genuid(), $mdID, $data[$x], undef);
}
endMessage($doc);
unless(callLS($self, $sender, $doc->getValue()) == 0) {
$logger->error("Unable to register data with LS.");
return -1;
}
}
return 0;
}
if (not defined $self->{URI}) {
return -1;
}
if(!$self->{ALIVE}) {
my $echo_service = perfSONAR_PS::Client::Echo->new($self->{URI});
my ($status, $res) = $echo_service->ping();
if ($status == -1) {
$logger->error("Ping to ".$self->{URI}." failed: $res");
return -1;
}
$self->{ALIVE} = 1;
}
if($self->{FIRST}) {
if ($self->sendDeregister($self->{CONF}->{"SERVICE_ACCESSPOINT"}) == 0) {
$logger->debug("Nothing registered.");
}
else {
$logger->debug("Removed old registration.");
}
my @resultsString = @{$data_ref};
if($#resultsString != -1) {
if ($self->__register(createService($self), $data_ref) == -1) {
$logger->error("Unable to register data with LS.");
$self->{ALIVE} = 0;
}
}
} else {
my @resultsString = @{$data_ref};
my $subject = "";
if ($self->sendKeepalive() == -1) {
$subject = createService($self);
}
else {
$subject = createKey($self, $self->{CONF}->{SERVICE_ACCESSPOINT})."\n".createService($self);
}
if($#resultsString != -1) {
if ($self->__register($subject, $data_ref) == -1) {
$logger->error("Unable to register data with LS.");
$self->{ALIVE} = 0;
return -1;
}
}
}
$self->{FIRST} = 0 if ($self->{FIRST});
return 0;
}
if (not defined $self->{URI}) {
return -1;
}
my ($host, $port, $endpoint) = &perfSONAR_PS::Transport::splitURI($self->{URI});
if (not defined $host and not defined $port and not defined $endpoint) {
return -1;
}
my $request = "";
$request .= "<nmwg:message type=\"LSQueryRequest\" id=\"msg1\"\n";
$request .= " xmlns:nmwg=\"http://ggf.org/ns/nmwg/base/2.0/\"\n";
$request .= " xmlns:xquery=\"http://ggf.org/ns/nmwg/tools/org/perfsonar/service/lookup/xquery/1.0/\">\n";
foreach my $query_id (keys %{ $queries }) {
$request .= " <nmwg:metadata id=\"perfsonar_ps.meta.$query_id\">\n";
$request .= " <xquery:subject id=\"sub1\">\n";
$request .= $queries->{$query_id};
$request .= " </xquery:subject>\n";
$request .= " <nmwg:eventType>http://ggf.org/ns/nmwg/tools/org/perfsonar/service/lookup/xquery/1.0</nmwg:eventType>\n";
$request .= " <xquery:parameters id=\"params.1\">\n";
$request .= " <nmwg:parameter name=\"lsOutput\">native</nmwg:parameter>\n";
$request .= " </xquery:parameters>\n";
$request .= " </nmwg:metadata>\n";
$request .= " <nmwg:data metadataIdRef=\"perfsonar_ps.meta.$query_id\" id=\"data.$query_id\"/>\n";
}
$request .= "</nmwg:message>\n";
my ($status, $res) = consultArchive($host, $port, $endpoint, $request);
if ($status != 0) {
my $msg = "Error consulting LS: $res";
$logger->error($msg);
return -1;
}
$logger->debug("Response: ".$res->toString);
my %ret_structure = ();
foreach my $d ($res->getChildrenByTagName("nmwg:data")) {
foreach my $m ($res->getChildrenByTagName("nmwg:metadata")) {
my $md_id = $m->getAttribute("id");
my $md_idref = $m->getAttribute("metadataIdRef");
my $d_idref = $d->getAttribute("metadataIdRef");
if($md_id eq $d_idref) {
my $query_id;
my $eventType = findvalue($m, "nmwg:eventType");
if (defined $md_idref and $md_idref =~ /perfsonar_ps\.meta\.(.*)/x) {
$query_id = $1;
} elsif ($md_id =~ /perfsonar_ps\.meta\.(.*)/x) {
$query_id = $1;
} else {
my $msg = "Received unknown response: $md_id/$md_idref";
$logger->error($msg);
next;
}
my @retval;
if (defined $eventType and $eventType =~ /^error\./x) {
my $error_msg = findvalue($d, "./nmwgr:datum");
$error_msg = "Unknown error" if (not defined $error_msg or $error_msg eq "");
@retval = (-1, $error_msg);
} else {
@retval = (0, $d);
}
$ret_structure{$query_id} = \@retval;
}
}
}
return (0, \%ret_structure);
}
1;
__END__
Log::Log4perl, perfSONAR_PS::Common, perfSONAR_PS::Transport, perfSONAR_PS::Messages, perfSONAR_PS::Client::Echo
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. Bugs, feature requests, and improvements can be directed here:
https://bugs.internet2.edu/jira/browse/PSPS
$Id$
Aaron Brown, aaron@internet2.edu Jason Zurawski, zurawski@internet2.edu
You should have received a copy of the Internet2 Intellectual Property Framework along with this software. If not, see <http://www.internet2.edu/membership/ip.html>
Copyright (c) 2004-2008, Internet2 and the University of Delaware
All rights reserved.
| perfSONAR_PS-Client-LS-Remote documentation | view source | Contained in the perfSONAR_PS-Client-LS-Remote distribution. |