example rest apis working with new json structure

This commit is contained in:
Bruce Potter 2014-02-23 04:13:15 -05:00
parent aea43684c3
commit e251f0a2cf
3 changed files with 164 additions and 154 deletions

View File

@ -1,5 +1,5 @@
#!/usr/bin/env perl
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
# This is a command which can be used to access the rest api of xCAT
@ -19,6 +19,10 @@ my $usage_string = "Usage:
-f The output format of the requested action
-V Display the verbose message\n";
#todo: make the code below into functions so that this file can be used for 2 purposes:
# 1. contain all the test cases that can all be run at once
# 2. if arguments are passed in, run the one api call passed in
# Parse the argument
$Getopt::Long::ignorecase = 0;
Getopt::Long::Configure( "bundling" );

View File

@ -1,41 +1,30 @@
#!/bin/bash
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
# * test & doc all current calls
# - finish test driver (both curl and natively from perl)
# * add debugging and fix bugs
# - change xdsh/xdcp to post and compact that code
# - change format of all put and post calls
# - change structure of output json and add Returns lines to doc
# - add nodeset stat
# - change table routines to use lissa's xml interface and doc them as an alternative to the node def calls
# - add: osimage def create, change, delete and copycds (bai yuan)
# - eliminate pw in url - api key or certificates (bai yuan)
# - send output back to client as it comes from xcatd, and compare code to Client.pm (bai yuan)
# - is the data sent back given the correct Content/Type? (bai yuan)
# - test, fix, doc the other resource handlers in there: groups, logs, notifications, policies, accounts, hypervisor(bai yuan)
# - do perf/scale tests and optimize code, incl breaking resource handlers into separate pms
# - return metadata of resources (list of possible attributes of def objects)(bai yuan)
# Test driver for xcatws.cgi
userpw = 'userName=bp&password=bryan1'
format = 'format=xml'
user = ''
pw = ''
format = 'format=json&pretty=1'
#curl -X GET -k 'http://127.0.0.1/xcatws/nodes?userName=bp&password=bryan1&format=xml'
curl -X GET -k 'https://127.0.0.1/xcatws/nodes?userName=bp&password=bryan1&format=xml'
curl -X GET -k 'https://127.0.0.1/xcatws/nodes?userName=bp&password=bryan1&format=xml&field=mac'
curl -X GET -k 'https://127.0.0.1/xcatws/nodes/test001-test006?userName=bp&password=bryan1&format=xml'
curl -X GET -k 'https://127.0.0.1/xcatws/nodes/test001-test006?userName=bp&password=bryan1&format=xml&field=mac'
#curl -X PUT -k --data '{"room":"foo"}' 'https://127.0.0.1/xcatws/nodes/test001?userName=bp&password=bryan1'
#curl -X POST -k --data '{"groups":"compute,all"}' 'https://127.0.0.1/xcatws/nodes/test001?userName=bp&password=bryan1'
curl -X DELETE -k 'http://127.0.0.1/xcatws/nodes/test001?userName=bp&password=bryan1'
curl -X PUT -k 'https://127.0.0.1/xcatws/nodes/test001?userName=bp&password=bryan1&format=xml&debug=0' -H Content-Type:application/json --data '{"room":"hi","unit":"7"}'
curl -X POST -k 'https://127.0.0.1/xcatws/nodes/ws1?userName=bp&password=bryan1&format=xml&debug=0' -H Content-Type:application/json --data '{"groups":"wstest"}'
#todo: add a test case for every api call that is documented
#todo: figure out why i currently have to specify -k
curl -X GET -k 'https://127.0.0.1/xcatws/groups?userName=bp&password=bryan1&format=xml'
curl -X GET -k "https://127.0.0.1/xcatws/nodes?userName=$user&password=$pw&format=xml"
curl -X GET -k "https://127.0.0.1/xcatws/nodes?userName=$user&password=$pw&format=xml&field=mac"
curl -X GET -k "https://127.0.0.1/xcatws/nodes/test001-test006?userName=$user&password=$pw&format=xml"
curl -X GET -k "https://127.0.0.1/xcatws/nodes/test001-test006?userName=$user&password=$pw&format=xml&field=mac"
curl -X DELETE -k "http://127.0.0.1/xcatws/nodes/test001?userName=$user&password=$pw"
curl -X PUT -k "https://127.0.0.1/xcatws/nodes/test001?userName=$user&password=$pw&format=xml&debug=0" -H Content-Type:application/json --data '{"room":"hi","unit":"7"}'
curl -X POST -k "https://127.0.0.1/xcatws/nodes/ws1?userName=$user&password=$pw&format=xml&debug=0" -H Content-Type:application/json --data '{"groups":"wstest"}'
curl -X GET -k 'https://127.0.0.1/xcatws/images?userName=bp&password=bryan1&format=xml'
curl -X GET -k 'https://127.0.0.1/xcatws/images?userName=bp&password=bryan1&format=xml&field=osvers'
curl -X GET -k 'https://127.0.0.1/xcatws/images/bp-netboot?userName=bp&password=bryan1&format=xml'
curl -X GET -k 'https://127.0.0.1/xcatws/images/bp-netboot?userName=bp&password=bryan1&format=xml&field=osvers'
curl -X GET -k "https://127.0.0.1/xcatws/groups?userName=$user&password=$pw&format=xml"
./xcatws-test.pl -u "https://127.0.0.1/xcatws/nodes/test001?userName=bp&password=bryan1" -m GET
./xcatws-test.pl -u "https://127.0.0.1/xcatws/nodes/test001?userName=bp&password=bryan1" -m PUT "nodepos.room=foo"
curl -X GET -k "https://127.0.0.1/xcatws/images?userName=$user&password=$pw&format=xml"
curl -X GET -k "https://127.0.0.1/xcatws/images?userName=$user&password=$pw&format=xml&field=osvers"
curl -X GET -k "https://127.0.0.1/xcatws/images/bp-netboot?userName=$user&password=$pw&format=xml"
curl -X GET -k "https://127.0.0.1/xcatws/images/bp-netboot?userName=$user&password=$pw&format=xml&field=osvers"
#todo: remove when these test cases are in xcatws-test.pl
./xcatws-test.pl -u "https://127.0.0.1/xcatws/nodes/test001?userName=$user&password=$pw" -m GET
./xcatws-test.pl -u "https://127.0.0.1/xcatws/nodes/test001?userName=$user&password=$pw" -m PUT "nodepos.room=foo"

View File

@ -1,4 +1,5 @@
#!/usr/bin/perl
# IBM(c) 2014 EPL license http://www.eclipse.org/legal/epl-v10.html
use strict;
use CGI qw/:standard/; #todo: remove :standard when the code only uses object oriented interface
use JSON; #todo: require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON
@ -16,7 +17,7 @@ use xCAT::Table;
# ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi
# - also upgraded CGI to 3.52
# - If "Internal Server Error" is returned, look at /var/log/httpd/ssl_error_log
# -can run your cgi script from the cli: http://perldoc.perl.org/CGI.html#DEBUGGING
# - can run your cgi script from the cli: http://perldoc.perl.org/CGI.html#DEBUGGING
# This is how the parameters come in:
# GET: url parameters come $q->url_param. There is no put/post data.
@ -78,7 +79,7 @@ if ($DEBUGGING) {
#if (defined($q->param('PUTDATA')) || defined($q->param('POSTDATA'))) {
# addPageContent("put data 1 " . $q->p($q->param('PUTDATA') . "\n"));
#} elsif (isPut()) {
# my $entries = JSON::decode_json($q->param('PUTDATA'));
# my $entries = $JSON->decode($q->param('PUTDATA'));
# if (scalar(@$entries) >= 1) {
# addPageContent("put data 2 \n");
# foreach (@$entries) {
@ -129,31 +130,33 @@ my %formatters = (
# puts $queryString into %queryHash
fetchParameter($queryString); #todo: remove when not used anymore
fetchParameter($queryString); #todo: stop using and then remove when not used anymore
if (!exists $formatters{$format}) {
addPageContent("The format '$format' is not supported");
sendResponseMsg($STATUS_BAD_REQUEST);
}
my $JSON; # global ptr to the json object
if ($format eq 'json' || isPut() || isPost()) {
# require JSON dynamically and let them know if it is not installed
my $jsoninstalled = eval { require JSON; };
unless ($jsoninstalled) {
addPageContent('{"data":"JSON perl module missing. Install perl-JSON before using the xCAT REST web services API."}');
sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
error("JSON perl module missing. Install perl-JSON before using the xCAT REST web services API.", $STATUS_SERVICE_UNAVAILABLE);
}
$JSON = JSON->new();
if ($q->url_param('pretty')) { $JSON->indent(1); }
}
if ($format eq 'xml') {
# require XML dynamically and let them know if it is not installed
my $xmlinstalled = eval { require XML::Simple; };
unless ($xmlinstalled) {
addPageContent('The XML::Simple perl module is missing. Install perl-XML-Simple before using the xCAT REST web services API with this format."}');
sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
}
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
#debugandexit('here');
# require XML dynamically and let them know if it is not installed
# we need XML all the time to send request to xcat, even if thats not the return format requested by the user
my $xmlinstalled = eval { require XML::Simple; };
unless ($xmlinstalled) {
addPageContent('The XML::Simple perl module is missing. Install perl-XML-Simple before using the xCAT REST web services API with this format."}');
sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
}
$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
#debugandexit('here');
#resource handlers
my %resources = (
@ -190,7 +193,7 @@ if ($pathInfo =~ /^\/$/ || $pathInfo =~ /^$/) {
my $formatType; # global var for tablesHandler to pass the splitCommas option to wrapHtml
#general tests for valid requests and responses with HTTP codes here
if (!doesResourceExist($resource)) {
if (!exists($resources{$resource})) {
addPageContent("Resource '$resource' does not exist");
sendResponseMsg($STATUS_NOT_FOUND); # this will also exit
}
@ -235,8 +238,7 @@ sub nodesHandler {
if (defined $path[2]) {
$subResource = $path[2];
unless (defined($noderange)) {
addPageContent("Invalid nodes and/or groups in noderange");
sendResponseMsg($STATUS_BAD_REQUEST);
error("Invalid nodes and/or groups in noderange",$STATUS_BAD_REQUEST);
}
$request->{noderange} = $noderange;
@ -284,8 +286,7 @@ sub nodesHandler {
}
}
else {
addPageContent("Unspported operation on nodes object.");
sendResponseMsg($STATUS_BAD_REQUEST);
error("Unspported operation on nodes object.",$STATUS_BAD_REQUEST);
}
}
else {
@ -311,31 +312,17 @@ sub nodesHandler {
my $entrydata;
unless (defined($noderange)) {
addPageContent("Invalid nodes and/or groups in noderange");
sendResponseMsg($STATUS_BAD_REQUEST);
error("Invalid nodes and/or groups in noderange",$STATUS_BAD_REQUEST);
}
$request->{noderange} = $noderange;
unless ($q->param('PUTDATA')) {
#temporary allowance for the put data to be contained in the queryString
# unless ($queryhash{'putData'}) {
addPageContent("No set attribute was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
# }
# else {
# foreach my $put (@{$queryhash{'putData'}}) {
# debug("put=$put");
# my ($key, $value) = split(/=/, $put, 2);
# if ($key eq 'field' && $value) {
# push @entries, $value;
# }
# }
# }
error("No set attribute was supplied.",$STATUS_BAD_REQUEST);
}
else {
# decode_json returns a reference to an array or hash
$entries = eval { JSON::decode_json($q->param('PUTDATA')); };
if ($@) { addPageContent ("$@"); sendResponseMsg($STATUS_BAD_REQUEST); }
$entries = eval { $JSON->decode($q->param('PUTDATA')); };
if ($@) { error("$@",$STATUS_BAD_REQUEST); }
debug("entries=" . Dumper($entries));
#if (scalar(@entries) < 1) {
# addPageContent("No set attribute was supplied.");
@ -365,8 +352,7 @@ sub nodesHandler {
extractData(\%elements, @$entries);
unless (scalar(%elements)) {
addPageContent("No power operands were supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
error("No power operands were supplied.",$STATUS_BAD_REQUEST);
}
}
elsif ($subResource eq "energy") {
@ -503,20 +489,15 @@ sub nodesHandler {
push @args, $elements{'target'};
}
}
else { msg('error',"unsupported node resource $subResource."); sendResponseMsg($STATUS_BAD_REQUEST); }
else { error("unsupported node resource $subResource.", $STATUS_BAD_REQUEST); }
}
else { # setting node attributes in the db
#my %elements;
#my $name;
#my $val;
#$request->{command} = "tabch";
#push @args, "node=" . $request->{noderange};
#todo: change this to use lissa's routines
$request->{command} = "chdef";
push @args, "-t", "node";
push @args, "-o", $request->{noderange};
#extractData(\%elements, @entries);
# input is a json object with key/value pairs
while (my ($name, $val) = each (%$entries)) {
push @args, $name . "=" . $val;
}
@ -527,22 +508,21 @@ sub nodesHandler {
push @args, "-t", "node";
unless (defined($noderange)) {
addPageContent("No nodename was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
error("No nodename was supplied.",$STATUS_BAD_REQUEST);
}
push @args, "-o", $noderange;
if ($q->param('POSTDATA')) {
# decode_json returns a reference to an array or hash
my $entries = eval { JSON::decode_json($q->param('POSTDATA')); };
if ($@) { addPageContent ("$@"); sendResponseMsg($STATUS_BAD_REQUEST); }
my $entries = eval { $JSON->decode($q->param('POSTDATA')); };
if ($@) { error("$@",$STATUS_BAD_REQUEST); }
debug("entries=" . Dumper($entries));
while (my ($name, $val) = each (%$entries)) {
push @args, $name . "=" . $val;
}
}
else { msg('error', 'no post data given.'); sendResponseMsg($STATUS_BAD_REQUEST); }
else { error('no post data given.', $STATUS_BAD_REQUEST); }
}
elsif (isDelete()) {
@ -550,14 +530,12 @@ sub nodesHandler {
$request->{command} = 'rmdef';
push @args, "-t", "node";
unless (defined($noderange)) {
addPageContent("No nodename was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
error("No nodename was supplied.",$STATUS_BAD_REQUEST);
}
push @args, "-o", $noderange;
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -668,7 +646,6 @@ sub groupsHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -715,7 +692,7 @@ sub imagesHandler {
addPageContent("Invalid Parameters");
sendResponseMsg($STATUS_BAD_REQUEST);
}
$entries = JSON::decode_json($q->param('POSTDATA'));
$entries = $JSON->decode($q->param('POSTDATA'));
if (scalar(@$entries) < 1) {
addPageContent("No set attribute was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
@ -864,7 +841,6 @@ sub imagesHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -966,7 +942,6 @@ sub logsHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1043,7 +1018,6 @@ sub monitorsHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1102,10 +1076,10 @@ sub networksHandler {
push @{$request->{arg}}, '-t', 'network', '-o', $netname;
if (defined($q->param('PUTDATA'))) {
$entries = JSON::decode_json($q->param('PUTDATA'));
$entries = $JSON->decode($q->param('PUTDATA'));
}
elsif (defined($q->param('POSTDATA'))) {
$entries = JSON::decode_json($q->param('POSTDATA'));
$entries = $JSON->decode($q->param('POSTDATA'));
}
else {
addPageContent("No Field and Value map was supplied.");
@ -1135,7 +1109,6 @@ sub networksHandler {
}
else {
unsupportedRequestType();
exit(0);
}
@responses = sendRequest(genRequest());
@ -1214,7 +1187,6 @@ sub notificationsHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1313,7 +1285,6 @@ sub policiesHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1360,7 +1331,7 @@ sub siteHandler {
}
} else {
if ($q->param('PUTDATA')) {
my $entries = JSON::decode_json($q->param('PUTDATA'));
my $entries = $JSON->decode($q->param('PUTDATA'));
foreach (@$entries) {
push @{$request->{arg}}, $_;
}
@ -1439,7 +1410,7 @@ sub tablesHandler {
}
}
else {
$entries = JSON::decode_json($q->param('PUTDATA'));
$entries = $JSON->decode($q->param('PUTDATA'));
if (scalar(@$entries) < 1) {
addPageContent("No set attribute was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
@ -1488,7 +1459,6 @@ sub tablesHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1619,7 +1589,6 @@ sub accountsHandler {
}
else {
unsupportedRequestType();
exit(0);
}
push @{$request->{arg}}, @args;
@ -1788,7 +1757,6 @@ sub objectsHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1847,7 +1815,7 @@ sub vmsHandler {
}
#collect all parameters from the postdata
my $entries = JSON::decode_json($q->param('POSTDATA'));
my $entries = $JSON->decode($q->param('POSTDATA'));
if (scalar(@$entries) < 1) {
addPageContent("No set attribute was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
@ -1939,7 +1907,7 @@ sub vmsHandler {
elsif (isPut()) {
$request->{command} = 'chvm';
if ($q->param('PUTDATA')) {
my $entries = JSON::decode_json($q->param('PUTDATA'));
my $entries = $JSON->decode($q->param('PUTDATA'));
if (scalar(@$entries) < 1) {
addPageContent("No Field and Value map was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
@ -1965,7 +1933,6 @@ sub vmsHandler {
}
else {
unsupportedRequestType();
exit();
}
push @{$request->{arg}}, @args;
@ -1999,7 +1966,7 @@ sub hypervisorHandler {
else {
$request->{command} = 'chhypervisor';
}
my $entries = JSON::decode_json( $q->param('PUTDATA') );
my $entries = $JSON->decode( $q->param('PUTDATA') );
if (scalar(@$entries) < 1) {
addPageContent("No set attribute was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
@ -2029,7 +1996,7 @@ sub debugHandler {
$request->{command} = 'xcatclientnnr xcatdebug';
#push @args, 'xcatdebug';
my $entries = JSON::decode_json( $q->param('PUTDATA') );
my $entries = $JSON->decode( $q->param('PUTDATA') );
if (scalar(@$entries) < 1) {
addPageContent("No set attribute was supplied.");
sendResponseMsg($STATUS_BAD_REQUEST);
@ -2058,15 +2025,17 @@ sub debugandexit {
sendResponseMsg($STATUS_OK);
}
# add a msg to the output in the correct format
sub msg {
my ($severity, $str) = @_;
if (!$severity) { $severity = 'info'; }
# add a error msg to the output in the correct format and end this request
#todo: replace all addPageContent/sendResponseMsg pairs to call this function instead
sub error {
my ($msg, $errorcode) = @_;
my $severity = 'error';
my $m;
if ($format eq 'xml') { $m = "<$severity>$str</$severity>\n"; }
elsif ($format eq 'json') { $m = qq({"$severity":"$str"}\n); }
else { $m = "<p>$severity: $str</p>\n"; }
if ($format eq 'xml') { $m = "<$severity>$msg</$severity>\n"; }
elsif ($format eq 'json') { $m = qq({"$severity":"$msg"}\n); }
else { $m = "<p>$severity: $msg</p>\n"; }
addPageContent($m);
sendResponseMsg($errorcode);
}
# Append content to the global var holding the output to go back to the rest client
@ -2081,15 +2050,9 @@ sub addPageContent {
sub sendResponseMsg {
my $code = shift;
my $tempFormat = '';
if ('json' eq $format) {
$tempFormat = 'application/json';
}
elsif ('xml' eq $format) {
$tempFormat = 'text/xml';
}
else {
$tempFormat = 'text/html';
}
if ('json' eq $format) { $tempFormat = 'application/json'; }
elsif ('xml' eq $format) { $tempFormat = 'text/xml'; }
else { $tempFormat = 'text/html'; }
print $q->header(-status => $code, -type => $tempFormat);
print $pageContent;
exit(0);
@ -2108,12 +2071,8 @@ sub genRequest {
my $xml = XML::Simple::XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []);
}
sub doesResourceExist {
my $res = shift;
return exists $resources{$res};
}
#when use put and post, can not fetch the url-parameter, so add this sub to support all kinds of methods
# when use put and post, can not fetch the url-parameter, so add this sub to support all kinds of methods
#todo: stop using this. Can always get parms thru $q->url_param, regardless of the request type
sub fetchParameter {
my $parstr = shift;
unless ($parstr) {
@ -2130,7 +2089,7 @@ sub fetchParameter {
}
# Extract the put data or post data into the hash that is passed in by reference.
# The data (2nd parameter) comes from JSON::decode_json()
# The data (2nd parameter) comes from $JSON->decode()
#todo: remove when not used any more
sub extractData {
my $returnhash = shift;
@ -2167,17 +2126,16 @@ sub wrapData {
#trim the serverdone message off
if (exists $data->[0]->{serverdone} && exists $data->[0]->{error}) {
$errorInformation = $data->[0]->{error}->[0];
addPageContent($q->p($errorInformation));
addPageContent($q->p($errorInformation)); #todo: put this in the requested format?
if (($errorInformation =~ /Permission denied/) || ($errorInformation =~ /Authentication failure/)) {
sendResponseMsg($STATUS_UNAUTH);
}
else {
sendResponseMsg($STATUS_FORBIDDEN);
}
exit 1;
}
else {
pop @{$data};
pop @{$data}; #todo: are we sure this is the serverdone entry?
}
# Call the appropriate formatting function stored in the formatters hash
@ -2185,7 +2143,7 @@ sub wrapData {
$formatters{$format}->($data);
}
# all output has been added into the global varibale pageContent, call the response funcion
# all output has been added into the global varibale pageContent, now complete the response to the user
if (exists $data->[0]->{info} && $data->[0]->{info}->[0] =~ /Could not find an object/) {
sendResponseMsg($STATUS_NOT_FOUND);
}
@ -2197,25 +2155,89 @@ sub wrapData {
}
}
# Structure the response perl data structure into well-formed json. Since the structure of the
# xml output that comes from xcatd is inconsistent and not very structured, we have a lot of work to do.
sub wrapJson {
# this is an array of responses from xcatd. Often all the output comes back in 1 response, but not always.
my $data = shift;
# put, post, and delete usually just give a short msg, if anything
if (isPut() || isPost() || isDelete() || isPatch()) {
addPageContent($JSON->encode($data));
return;
}
# Divide the processing into several groups of requests, according to how they return the output
# At this point, these are all gets
my $json;
$json->{'data'} = $data;
addPageContent(JSON::to_json($json));
if ($resource eq 'nodes') {
if (!defined $path[2]) { # querying node attributes
# The data structure is: array of hashes that have a single key 'info'. The value for that key
# is an array of lines of lsdef output (all nodes in the same array).
# Create a json array of node objects. Each node object contains the attributes/values (including
# the nodename) of that object.
$json = [];
foreach my $d (@$data) {
my $jsonnode;
my $lines = $d->{info};
foreach my $l (@$lines) {
if ($l =~ /^Object name: /) { # start new node
if (defined($jsonnode)) { push @$json, $jsonnode; } # push previous object onto array
my ($nodename) = $l =~ /^Object name:\s+(\S+)/;
$jsonnode = { nodename => $nodename };
}
else { # just an attribute of the current node
if (!defined($jsonnode)) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); }
my ($attr, $val) = $l =~ /^\s*(\S+)=(.*)$/;
if (!defined($attr)) { error('improperly formatted lsdef output from xcatd', $STATUS_TEAPOT); }
$jsonnode->{$attr} = $val;
}
}
if (defined($jsonnode)) { push @$json, $jsonnode; $jsonnode=undef; } # push last object onto array
}
addPageContent($JSON->encode($json));
}
elsif (grep(/^$path[2]$/, qw(power inventory vitals energy))) { # querying other node info
# The data structure is: array of hashes that have a single key 'node'. The value for that key
# is a 1-element array that has a hash with keys 'name' and 'data'. The 'name' value is a 1-element
# array that has the nodename. The 'data' value is a 1-element array of a hash that has keys 'desc'
# and 'content' (sometimes desc is ommited).
# Create a json array of node objects. Each node object contains the attributes/values (including
# the nodename) of that object.
$json = {}; # its keys are nodenames
foreach my $d (@$data) {
# each element is a complex structure that contains 1 attr and value for a node
my $node = $d->{node}->[0];
my $nodename = $node->{name}->[0];
my $nodedata = $node->{data}->[0];
my $contents = $nodedata->{contents}->[0];
my $desc = 'power'; # rpower doesn't output a desc tag
if (defined($nodedata->{desc})) { $desc = $nodedata->{desc}->[0]; }
# add this desc and content into this node's hash
$json->{$nodename}->{$desc} = $contents;
}
# convert this hash of hashes into an array of hashes
my @jsonarray;
foreach my $n (sort(keys(%$json))) {
$json->{$n}->{nodename} = $n; # add the key (nodename) inside of the node's hash
push @jsonarray, $json->{$n};
}
addPageContent($JSON->encode(\@jsonarray));
}
else { # querying a node subresource (rpower, rvitals, rinv, etc.)
addPageContent($JSON->encode($data));
} # end else path[2] defined
} # end if nodes
}
sub wrapHtml {
my $item;
my $response = shift;
#my $baseUri = $url . $pathInfo;
#if ($baseUri !~ /\/^/) {
# $baseUri .= "/";
#}
foreach my $element (@$response) {
#foreach my $element (@$data){
#if($element->{error}){
if ($element->{node}) {
addPageContent("<table border=1>");
foreach $item (@{$element->{node}}) {
@ -2351,12 +2373,10 @@ sub sendRequest {
}
unless ($client) {
if ($@ =~ /SSL Timeout/) {
addPageContent("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat");
sendResponseMsg($STATUS_TIMEOUT);
error("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat",$STATUS_TIMEOUT);
}
else {
addPageContent("Connection failurexx: $@");
sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
error("Connection failurexx: $@",$STATUS_SERVICE_UNAVAILABLE);
}
}
@ -2401,9 +2421,7 @@ sub sendRequest {
}
}
unless ($cleanexit) {
addPageContent("ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely");
sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
exit(0);
error("communication with the xCAT server seems to have been ended prematurely",$STATUS_SERVICE_UNAVAILABLE);
}
if ($DEBUGGING) {
@ -2436,6 +2454,5 @@ sub isAuthenticUser {
}
#authentication failure
addPageContent($responses[0]->{error}[0]);
sendResponseMsg($STATUS_UNAUTH);
error($responses[0]->{error}[0], $STATUS_UNAUTH);
}