diff --git a/xCAT-server/xCAT-wsapi/xcatws.cgi b/xCAT-server/xCAT-wsapi/xcatws.cgi
deleted file mode 100755
index 84701929a..000000000
--- a/xCAT-server/xCAT-wsapi/xcatws.cgi
+++ /dev/null
@@ -1,2521 +0,0 @@
-#!/usr/bin/perl
-use strict;
-use CGI qw/:standard/;
-#use JSON; # require this dynamically later on so that installations that do not use xcatws.cgi do not need perl-JSON
-use Data::Dumper;
-
-#added the line:
-#ScriptAlias /xcatws /var/www/cgi-bin/xcatws.cgi
-#to /etc/httpd/conf/httpd.conf to hid the cgi-bin and .cgi extension in the uri
-#
-# also upgraded CGI to 3.52
-
-#take the JSON or XML and put it into a data structure
-#all data input will be done from the common structure
-
-#turn on or off the debugging output
-my $DEBUGGING = 0;
-my $VERSION = "2.8";
-
-my $q = CGI->new;
-my $url = $q->url;
-my $pathInfo = $q->path_info;
-my $requestType = $ENV{'REQUEST_METHOD'};
-my $queryString = $ENV{'QUERY_STRING'};
-my %queryhash;
-my @path = split(/\//, $pathInfo);
-shift(@path);
-my $resource = $path[0];
-my $pageContent = '';
-my $request = {clienttype => 'ws'};
-
-#error status codes
-my $STATUS_BAD_REQUEST = "400 Bad Request";
-my $STATUS_UNAUTH = "401 Unauthorized";
-my $STATUS_FORBIDDEN = "403 Forbidden";
-my $STATUS_NOT_FOUND = "404 Not Found";
-my $STATUS_NOT_ALLOWED = "405 Method Not Allowed";
-my $STATUS_NOT_ACCEPTABLE = "406 Not Acceptable";
-my $STATUS_TIMEOUT = "408 Request Timeout";
-my $STATUS_EXPECT_FAILED = "417 Expectation Failed";
-my $STATUS_TEAPOT = "418 I'm a teapot";
-my $STATUS_SERVICE_UNAVAILABLE = "503 Service Unavailable";
-
-#good status codes
-my $STATUS_OK = "200 OK";
-my $STATUS_CREATED = "201 Created";
-
-#default format
-my $format = 'html';
-
-sub addPageContent {
- my $newcontent = shift;
- $pageContent .= $newcontent;
-}
-
-#send the response to client side
-#the http only return once in each request, so all content shoudl save in a global variable,
-#create the response header by status
-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';
- }
- print $q->header(-status => $code, -type => $tempFormat);
- print $pageContent;
- exit(0);
-}
-
-sub unsupportedRequestType {
- addPageContent("request method '$requestType' is not supported on resource '$resource'");
- sendResponseMsg($STATUS_NOT_ALLOWED);
-}
-
-use XML::Simple;
-$XML::Simple::PREFERRED_PARSER = 'XML::Parser';
-
-sub genRequest {
- if ($DEBUGGING) {
- addPageContent($q->p("request " . Dumper($request)));
- }
- my $xml = XMLout($request, RootName => 'xcatrequest', NoAttr => 1, KeyAttr => []);
-}
-
-#data formatters. To add one simple copy the format of an existing one
-# and add it to this hash
-my %formatters = (
- 'html' => \&wrapHtml,
- 'json' => \&wrapJson,
- 'xml' => \&wrapXml,);
-
-fetchParameter($queryString);
-
-if ($queryhash{'format'}) {
- $format = $queryhash{'format'}->[0];
- if (!exists $formatters{$format}) {
- addPageContent("The format '$format' is not valid");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if ($format eq 'json') {
- # 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);
- }
- }
-}
-
-my $XCAT_PATH = '/opt/xcat/bin';
-
-#resource handlers
-my %resources = (
- groups => \&groupsHandler,
- images => \&imagesHandler,
- logs => \&logsHandler,
- monitors => \&monitorsHandler,
- networks => \&networksHandler,
- nodes => \&nodesHandler,
- notifications => \¬ificationsHandler,
- policies => \&policiesHandler,
- site => \&siteHandler,
- tables => \&tablesHandler,
- accounts => \&accountsHandler,
- objects => \&objectsHandler,
- vms => \&vmsHandler,
- debug => \&debugHandler,
- hypervisor => \&hypervisorHandler,
- version => \&versionHandler);
-
-#if no resource was specified
-if ($pathInfo =~ /^\/$/ || $pathInfo =~ /^$/) {
- addPageContent($q->p("This is the root page for the xCAT Rest Web Service. Available resources are:"));
- foreach (sort keys %resources) {
- addPageContent($q->p($_));
- }
- sendResponseMsg($STATUS_OK);
-}
-
-sub doesResourceExist {
- my $res = shift;
- return exists $resources{$res};
-}
-
-if ($DEBUGGING) {
- if (defined $q->param('PUTDATA')) {
- addPageContent("put data " . $q->p($q->param('PUTDATA') . "\n"));
- } elsif (isPut()) {
- my $entries = JSON::decode_json($q->param('PUTDATA'));
- if (scalar(@$entries) >= 1) {
- addPageContent("put data \n");
- foreach (@$entries) {
- addPageContent("$_\n");
- }
- }
- }
-
- if (defined $q->param('POSTDATA')) {
- addPageContent("post data " . $q->p($q->param('POSTDATA') . "\n"));
- } elsif (isPost()) {
- my $entries = JSON::decode_json($q->param('POSTDATA'));
- if (scalar(@$entries) >= 1) {
- addPageContent("post data \n");
- foreach (@$entries) {
- addPageContent("$_\n");
- }
- }
- }
-
- addPageContent($q->p("Parameters "));
- my @params = $q->param;
- foreach (@params) {
- addPageContent("$_ = " . join(',', $q->param($_)) . "\n");
- }
- addPageContent($q->p("Query String $queryString" . "\n"));
- addPageContent($q->p("Query parameters from the Query String" . Dumper(\%queryhash) . "\n"));
- addPageContent($q->p("HTTP Method $requestType" . "\n"));
- addPageContent($q->p("URI $url" . "\n"));
- addPageContent($q->p("path " . Dumper(@path) . "\n"));
-}
-
-#when use put and post, can not fetch the url-parameter, so add this sub to support all kinks of method
-sub fetchParameter {
- my $parstr = shift;
- unless ($parstr) {
- return;
- }
-
- my @pairs = split(/&/, $parstr);
- foreach my $pair (@pairs) {
- my ($key, $value) = split(/=/, $pair, 2);
- $value =~ tr/+/ /;
- $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/chr(hex($1))/eg;
- push @{$queryhash{$key}}, $value;
- }
-}
-
-#extract the put data or post data into perl hash, easy for retrieve
-sub extractData {
- my $temphash = shift;
- my $parArray = shift;
- my $key;
- my $value;
- my $position;
-
- #traversal all element in the array
- foreach (@$parArray) {
- $position = index($_, '=');
- if ($position < 0) {
- $key = $_;
- $value = 1;
- }
- else {
- $key = substr $_, 0, $position;
- $value = substr $_, $position + 1;
- }
- $temphash->{$key} = $value;
-
- if ($DEBUGGING) {
- addPageContent($q->p("The parameter extract from put/post data:
" . Dumper($temphash)));
- }
- }
-}
-
-my $userName=http('userName');
-my $password=http('password');
-
-sub handleRequest {
- if (defined $queryhash{'userName'}) {
- $userName = $queryhash{'userName'}->[0];
- }
- if (defined $queryhash{'password'}) {
- $password = $queryhash{'password'}->[0];
- }
- if ($userName && $password) {
- $request->{becomeuser}->[0]->{username}->[0] = $userName;
- $request->{becomeuser}->[0]->{password}->[0] = $password;
- }
- my @data = $resources{$resource}->();
- wrapData(\@data);
-}
-
-my @groupFields = ('groupname', 'grouptype', 'members', 'wherevals', 'comments', 'disable');
-
-#get is done
-#post and delete are done but not tested
-#groupfiles4dsh is done but not tested
-sub groupsHandler {
- my @responses;
- my @args;
- my $groupName;
-
- #is the group name in the URI?
- if (defined $path[1]) {
- $groupName = $path[1];
- }
-
- #in the query string?
- else {
- $groupName = $q->param('groupName');
- }
-
- if (isGet()) {
- if (defined $groupName) {
- $request->{command} = 'gettab';
- push @args, "groupname=$groupName";
- if (defined $q->param('field')) {
- foreach ($q->param('field')) {
- push @args, "nodegroup.$_";
- }
- }
- else {
- foreach (@groupFields) {
- push @args, "nodegroup.$_";
- }
- }
- }
- else {
- $request->{command} = 'tabdump';
- push @args, 'nodegroup';
- }
- }
-
- #does it make sense to even have this?
- elsif (isPost()) {
- my $nodeRange = $q->param('nodeRange');
- if ((defined $groupName) && (defined $nodeRange)) {
- $request->{command} = 'mkdef';
- push @args, '-t';
- push @args, 'group';
- push @args, '-o';
- push @args, $groupName;
- push @args, "members=$nodeRange";
- }
- else {
- addPageContent("A node range and group name must be specified for creating a group");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif (isPut()) {
-
- #handle groupfiles4dsh -p /tmp/nodegroupfiles
- if ($q->param('command') eq "4dsh") {
- if ($q->param('path')) {
- $request->{command} = 'groupfiles4dsh';
- push @args, "p=$q->param('path')";
- }
- else {
- addPageContent("The path must be specified for creating directories for dsh");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- if (defined $groupName && defined $q->param('fields')) {
- $request->{command} = 'nodegrpch';
- push @args, $groupName;
- push @args, $q->param('field');
- }
- else {
- addPageContent("The group and fields must be specified to update groups");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- }
- elsif (isDelete()) {
- if (defined $groupName) {
- $request->{command} = 'rmdef';
- push @args, '-t';
- push @args, 'group';
- push @args, '-o';
- push @args, $groupName;
- }
- else {
- addPageContent("The group must be specified to delete a group");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-my @imageFields = (
- 'imagename', 'profile', 'imagetype', 'provmethod', 'osname', 'osvers',
- 'osdistro', 'osarch', 'synclists', 'comments', 'disable');
-
-#get is done, nothing else
-sub imagesHandler {
- my @responses;
- my @args;
- my $image;
- my $subResource;
-
- if (defined($path[1])) {
- $image = $path[1];
- }
-
- if (isGet()) {
- $request->{command} = 'lsdef';
- push @args, '-t', 'osimage';
- if (defined $image) {
- push @args, '-o', $image;
- }
- if (defined($q->param('field'))) {
- push @args, '-i';
- push @args, join(',', $q->param('field'));
- }
- if (defined($q->param('criteria'))) {
- foreach ($q->param('criteria')) {
- push @args, '-w', "$_";
- }
- }
- }
- elsif (isPost()) {
- my $operationname = $image;
- my $entries;
- my %entryhash;
-
- #check the post data
- unless (defined($q->param('POSTDATA'))) {
- addPageContent("Invalid Parameters");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- $entries = JSON::decode_json($q->param('POSTDATA'));
- if (scalar(@$entries) < 1) {
- addPageContent("No set attribute was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- extractData(\%entryhash, $entries);
-
- #for image capture
- if ($operationname eq 'capture') {
- $request->{command} = 'imgcapture';
- if (defined($entryhash{'nodename'})) {
- $request->{noderange} = $entryhash{'nodename'};
- }
- else {
- addPageContent('No node range.');
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (defined($entryhash{'profile'})) {
- push @args, '-p';
- push @args, $entryhash{'profile'};
- }
- if (defined($entryhash{'osimage'})) {
- push @args, '-o';
- push @args, $entryhash{'osimage'};
- }
- if (defined($entryhash{'bootinterface'})) {
- push @args, '-i';
- push @args, $entryhash{'bootinterface'};
- }
- if (defined($entryhash{'netdriver'})) {
- push @args, '-n';
- push @args, $entryhash{'netdriver'};
- }
- if (defined($entryhash{'device'})) {
- push @args, '-d';
- push @args, $entryhash{'device'};
- }
- if (defined($entryhash{'compress'})) {
- push @args, '-c';
- push @args, $entryhash{'compress'};
- }
- }
- elsif ($operationname eq 'export') {
- $request->{command} = 'imgexport';
- if (defined($entryhash{'osimage'})) {
- push @args, $entryhash{'osimage'};
- }
- else {
- addPageContent('No image specified');
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (defined($entryhash{'destination'})) {
- push @args, $entryhash{'destination'};
- }
- if (defined($entryhash{'postscripts'})) {
- push @args, '-p';
- push @args, $entryhash{'postscripts'};
- }
- if (defined($entryhash{'extra'})) {
- push @args, '-e';
- push @args, $entryhash{'extra'};
- }
- if (defined($entryhash{'remotehost'})) {
- push @args, '-R';
- push @args, $entryhash{'remotehost'};
- }
- if (defined($entryhash{'verbose'})) {
- push @args, '-v';
- }
- }
- elsif ($operationname eq 'import') {
- $request->{command} = 'imgimport';
- if (defined($entryhash{'osimage'})) {
- push @args, $entryhash{'osimage'};
- }
- else {
- addPageContent('No image specified');
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (defined($entryhash{'profile'})) {
- push @args, '-f';
- push @args, $entryhash{'profile'};
- }
- if (defined($entryhash{'remotehost'})) {
- push @args, '-R';
- push @args, $entryhash{'remotehost'};
- }
- if (defined($entryhash{'postscripts'})) {
- push @args, '-p';
- push @args, $entryhash{'postscripts'};
- }
- if (defined($entryhash{'nozip'})) {
- push @args, '-n';
- }
-
- if (defined($entryhash{'verbose'})) {
- push @args, '-v';
- }
- }
- }
- elsif (isPut()) {
-
- #check the operation type
- unless (defined $path[2]) {
- addPageContent("The subResource $subResource does not exist");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- $subResource = $path[2];
-
- #check the image name
- unless (defined $image) {
- addPageContent("The image name is required to clean an os image");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if ($subResource eq 'check') {
- $request->{command} = 'chkosimage';
- if (defined($q->param('PUTDATA'))) {
- push @args, '-c';
- }
- push @args, $image;
- }
- else {
- addPageContent("The subResource $subResource does not exist");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif (isDelete()) {
- if (defined $image) {
- $request->{command} = 'rmimage';
- if (defined $q->param('verbose')) {
- push @args, '-v';
- }
- push @args, $image;
- }
- elsif (defined $q->param('os') && defined $q->param('arch') && defined $q->param('profile')) {
- push @args, '-o';
- push @args, $q->param('os');
- push @args, '-a';
- push @args, $q->param('arch');
- push @args, '-p';
- push @args, $q->param('profile');
- }
- else {
- addPageContent(
- "Either the image name or the os, architecture and profile must be specified to remove an image");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-#complete
-sub logsHandler {
- my @responses;
- my @args;
- my $logType;
-
- if (defined $path[1]) {
- $logType = $path[1];
- }
-
- #in the query string?
- else {
- $logType = $q->param('logType');
- }
- my $nodeRange = $q->param('nodeRange');
-
- #no real output unless the log type is defined
- if (!defined $logType) {
- addPageContent("Current logs available are auditlog, eventlog, and diagnostics");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (isGet()) {
- if ($logType eq "reventLog") {
- if (defined $nodeRange) {
- $request->{command} = 'reventlog';
- push @args, $nodeRange;
- if (defined $q->param('count')) {
- push @args, $q->param('count');
- }
- }
- else {
- addPageContent("nodeRange must be specified to GET remote event logs");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif ($logType eq "diagnostics") {
- addPageContent(uc($requestType) . " remote diagnostic logs is not supported");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- else {
- $request->{command} = 'tabdump';
- push @args, $logType;
- }
- }
-
- #this clears the log
- elsif (isPut()) {
- if ($logType eq "reventlog") {
- if (defined $nodeRange) {
- $request->{command} = 'reventlog';
- push @args, $nodeRange;
- push @args, 'clear';
- }
- else {
- addPageContent("nodeRange must be specified to clean remote event logs");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif ($logType eq "diagnostics") {
- addPageContent(uc($requestType) . " remote diagnostic logs is not supported");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- else {
-
- #should it return the removed entries?
- if (defined $q->param('showRemoved')) {
- push @args, '-V';
- }
- if (defined $q->param('count') || defined $q->param('percent') || defined $q->param('lastRecord')) {
-
- #remove some of the entries
- $request->{command} = 'tabprune';
-
- #remove a certain number of records
- if (defined $q->param('count')) {
- push @args, ('-n', $q->param('count'));
- }
-
- #remove a percentage of the records
- if (defined $q->param('percent')) {
- push @args, ('-p', $q->param('percent'));
- }
-
- #remove all records before this record
- if (defined $q->param('lastRecord')) {
- push @args, ('-i', $q->param('lastRecord'));
- }
- }
- else {
- $request->{command} = 'tabprune';
-
- #-a removes all
- push @args, '-a';
- }
- }
- }
- # Currently, only diagnostic logs can be created
- elsif (isPost()) {
- if ($logType eq "diagnostics") {
-
- # Potential base bug on the reventlog and auditlog paths:
- # $q->param('nodeRange') != $queryhash{'nodeRange'}
- # The base code uses the first, which is undef even when a URL
- # query parameter named nodeRange was passed by the caller (e.g. is
- # found in the nova-compute.log traces).
- # Re-assigning nodeRange on this new path since it does return
- # a value.
-
- $nodeRange = $queryhash{'nodeRange'};
- if (defined $nodeRange) {
- $request->{command} = 'diagnostics';
- $request->{noderange} = $nodeRange;
-
- my $parameter;
- # Parse the optional upstream request ID, e.g. an OpenStack request UUID
- $parameter = 'requestid';
- if (defined $queryhash{$parameter}) {
- push @args, '--'.$parameter;
- push @args, $queryhash{$parameter}->[0];
- }
-
- # Parse the optional upstream object ID, e.g. an OpenStack nova instance UUID
- $parameter = 'objectid';
- if (defined $queryhash{$parameter}) {
- push @args, '--'.$parameter;
- push @args, $queryhash{$parameter}->[0];
- }
-
- unless ($q->param('POSTDATA')) {
- addPageContent("A request body containing parameters is required");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- # Collect all parameters from the postdata
- my %entryhash;
- my $entries = JSON::decode_json($q->param('POSTDATA'));
- if (scalar(@$entries) < 1) {
- addPageContent("No request parameters were supplied in the message body.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- extractData(\%entryhash, $entries);
- # TODO: add parameter parsing back in to pass through all body parameters.
- # How to handle duplicate property names? Perhaps prefix them with upstream_ , and pass the prefix too ;-)
-
- # Parse the optional body parameters from the caller (NOT URL query parameters)
- # TODO: this is early code that hard-codes a single key passed by the
- # z/VM OpenStack nova plugin. It will be replaced later with more
- # general code that behaves similarly.
- $parameter = 'reason';
- if (defined $entryhash{$parameter}) {
- push @args, '--upstream-'.$parameter;
- push @args, $entryhash{$parameter};
- }
-
- }
- else {
- addPageContent("nodeRange must be specified to collect diagnostics");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- addPageContent("POST is only valid for logType(s): diagnostics. It is not valid with the supplied logType: $logType");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-#complete
-sub monitorsHandler {
- my @responses;
- my @args;
- my $monitor;
-
- if (defined $path[1]) {
- $monitor = $path[1];
- }
-
- #in the query string?
- elsif (defined $q->param('monitor')) {
- push @args, $q->param('monitor');
- }
- if (defined $monitor) {
- push @args, $monitor;
- }
-
- if (isGet()) {
- $request->{command} = 'monls';
- }
- elsif (isPost()) {
- $request->{command} = 'monadd';
- if ($q->param('nodeStatMon')) {
- push @args, '-n';
- }
-
- #get the plug-in specific settings array
- foreach ($q->param('pluginSetting')) {
- push @args, '-s';
- push @args, $_;
- }
- }
- elsif (isDelete()) {
- $request->{command} = 'monrm';
- }
- elsif (isPut() || isPatch()) {
- my $action = $q->param('action');
- if ($action eq "start") {
- $request->{command} = 'monstart';
- }
- elsif ($action eq "stop") {
- $request->{command} = 'monstop';
- }
- elsif ($action eq "config") {
- $request->{command} = 'moncfg';
- }
- elsif ($action eq "deconfig") {
- $request->{command} = 'mondeconfig';
- }
- else {
- unsupportedRequestType();
- }
- if (!defined $q->param('nodeRange')) {
-
- #error
- }
- else {
- push @args, $q->param('nodeRange');
- }
- if (defined $q->param('remote')) {
- push @args, '-r';
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-sub networksHandler {
- my @responses;
- my @args;
- my $netname = '';
-
- if (isGet()) {
- $request->{command} = 'lsdef';
- push @{$request->{arg}}, '-t', 'network';
- if (defined($path[1])) {
- push @{$request->{arg}}, '-o', $path[1];
- }
- my @temparray = $q->param('field');
-
- #add the field name to get
- if (scalar(@temparray) > 0) {
- push @{$request->{arg}}, '-i';
- push @{$request->{arg}}, join(',', @temparray),;
- }
- }
- elsif (isPut() || isPost()) {
- my $entries;
- my $iscommand = 0;
- if (isPut()) {
- $request->{command} = 'chdef';
- if (defined($path[1])) {
- if ($path[1] eq "makehosts" || $path[1] eq "makedns") {
- # Issue makehost/makedns directly
- $request->{command} = $path[1];
- $iscommand = 1;
- }
- }
- }
- else {
- $request->{command} = 'mkdef';
- }
-
- if (!$iscommand) {
- if (defined $path[1]) {
- $netname = $path[1];
- }
-
- if ($netname eq '') {
- addPageContent('A network name must be specified.');
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- push @{$request->{arg}}, '-t', 'network', '-o', $netname;
-
- if (defined($q->param('PUTDATA'))) {
- $entries = JSON::decode_json($q->param('PUTDATA'));
- }
- elsif (defined($q->param('POSTDATA'))) {
- $entries = JSON::decode_json($q->param('POSTDATA'));
- }
- else {
- addPageContent("No Field and Value map was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (scalar($entries) < 1) {
- addPageContent("No Field and Value map was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- foreach (@$entries) {
- push @{$request->{arg}}, $_;
- }
- }
- }
- elsif (isDelete()) {
- $request->{command} = 'rmdef';
-
- if (defined $path[1]) {
- $netname = $path[1];
- }
- if ($netname eq '') {
- addPageContent('A network name must be specified.');
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- push @{$request->{arg}}, '-t', 'network', '-o', $netname;
- }
- else {
- unsupportedRequestType();
- exit(0);
- }
- @responses = sendRequest(genRequest());
-
- return @responses;
-}
-
-sub nodesHandler {
- my @responses;
- my @args;
- my $noderange;
- my @envs;
-
- if (defined $path[1]) {
- $noderange = $path[1];
- }
-
- if (isGet()) {
- my $subResource;
- if (defined $path[2]) {
- $subResource = $path[2];
- unless (defined($noderange)) {
- addPageContent("Invalid nodes and/or groups in noderange");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- $request->{noderange} = $noderange;
-
- #use the corresponding command by the subresource name
- if ($subResource eq "power") {
- $request->{command} = 'rpower';
-
- #no fields will default to 'stat'
- if (defined $q->param('field')) {
- push @args, $q->param('field');
- }
- else {
- push @args, 'stat';
- }
- }
- elsif ($subResource eq "energy") {
- $request->{command} = 'renergy';
-
- #no fields will default to 'all'
- if (defined $q->param('field')) {
- push @args, $q->param('field');
- }
- else {
- push @args, 'all';
- }
- }
- elsif ($subResource eq "status") {
- $request->{command} = 'nodestat';
- }
- elsif ($subResource eq "inventory") {
- $request->{command} = 'rinv';
- if (defined $q->param('field')) {
- push @args, $q->param('field');
- }
- else {
- push @args, 'all';
- }
- }
- elsif ($subResource eq "vitals") {
- $request->{command} = 'rvitals';
- if (defined $q->param('field')) {
- push @args, $q->param('field');
- }
- else {
- push @args, 'all';
- }
- }
- elsif ($subResource eq "scan") {
- $request->{command} = 'rscan';
- if (defined $q->param('field')) {
- push @args, $q->param('field');
- }
- }
- else {
- addPageContent("Unspported operation on nodes object.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- $request->{command} = 'lsdef';
- push @args, "-t", "node";
-
- #add the nodegroup into args
- if (defined($noderange)) {
- push @args, "-o", $noderange;
- }
-
- #maybe it's specified in the parameters
- my @temparray = $q->param('field');
- if (scalar(@temparray) > 0) {
- push @args, "-i";
- push @args, join(',', @temparray);
- }
- }
- }
- elsif (isPut()) {
- my $subResource;
- my @entries;
- my $entrydata;
-
- unless (defined($noderange)) {
- addPageContent("Invalid nodes and/or groups in noderange");
- sendResponseMsg($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'}}) {
- my ($key, $value) = split(/=/, $put, 2);
- if ($key eq 'field' && $value) {
- push @entries, $value;
- }
- }
- }
- }
- else {
- @entries = JSON::decode_json($q->param('PUTDATA'));
- if (scalar(@entries) < 1) {
- addPageContent("No set attribute was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
-
- if (defined $path[2]) {
- $subResource = $path[2];
-
- if (($subResource ne "dsh") && ($subResource ne "dcp")) {
- # For any function other than "dsh" or "dcp",
- # move all operands to the argument list.
- foreach (@entries) {
- if (ref($_) eq 'ARRAY') {
- foreach (@$_) {
- push @args, $_;
- }
- } else {
- push @args, $_;
- }
- }
- }
- if ($subResource eq "power") {
- $request->{command} = "rpower";
- my %elements;
- extractData(\%elements, @entries);
-
- unless (scalar(%elements)) {
- addPageContent("No power operands were supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif ($subResource eq "energy") {
- $request->{command} = "renergy";
- }
- elsif ($subResource eq "bootstat" or $subResource eq "bootstate") {
- $request->{command} = "nodeset";
- }
- elsif ($subResource eq "bootseq") {
- $request->{command} = "rbootseq";
- }
- elsif ($subResource eq "setboot") {
- $request->{command} = "rsetboot";
- }
- elsif ($subResource eq "migrate") {
- $request->{command} = "rmigrate";
- }
- elsif ($subResource eq "execcmdonvm") {
- $request->{command} = "execcmdonvm";
- }
- elsif ($subResource eq "dsh") {
- $request->{command} = "xdsh";
- my %elements;
- extractData(\%elements, @entries);
- if (defined($elements{'devicetype'})) {
- push @args, '--devicetype';
- push @args, $elements{'devicetype'};
- }
- if (defined($elements{'execute'})) {
- push @args, '-e';
- }
- if (defined($elements{'environment'})) {
- push @args, '-E';
- push @args, $elements{'environment'};
- }
- if (defined($elements{'fanout'})) {
- push @args, '-f';
- push @args, $elements{'fanout'};
- }
- if (defined($elements{'nolocale'})) {
- push @args, '-L';
- }
- if (defined($elements{'userid'})) {
- push @args, '-l';
- push @args, $elements{'userid'};
- }
- if (defined($elements{'monitor'})) {
- push @args, '-m';
- }
- if (defined($elements{'options'})) {
- push @args, '-o';
- push @args, $elements{'options'};
- }
- if (defined($elements{'showconfig'})) {
- push @args, '-q';
- }
- if (defined($elements{'silent'})) {
- push @args, '-Q';
- }
- if (defined($elements{'remoteshell'})) {
- push @args, '-r';
- push @args, $elements{'remoteshell'};
- }
- if (defined($elements{'syntax'})) {
- push @args, '-S';
- push @args, $elements{'syntax'};
- }
- if (defined($elements{'timeout'})) {
- push @args, '-t';
- push @args, $elements{'timeout'};
- }
- if (defined($elements{'envlist'})) {
- push @args, '-X';
- push @args, $elements{'envlist'};
- }
- if (defined($elements{'sshsetup'})) {
- push @args, '-K';
- push @args, $elements{'sshsetup'};
- }
- if (defined($elements{'rootimg'})) {
- push @args, '-i';
- push @args, $elements{'rootimg'};
- }
- if (defined($elements{'command'})) {
- push @args, $elements{'command'};
- }
- if (defined($elements{'remotepasswd'})) {
- push @envs, 'DSH_REMOTE_PASSWORD=' . $elements{'remotepasswd'};
- push @envs, 'DSH_FROM_USERID=root';
- push @envs, 'DSH_TO_USERID=root';
- }
- }
- elsif ($subResource eq "dcp") {
- $request->{command} = "xdcp";
- my %elements;
- extractData(\%elements, @entries);
- if (defined($elements{'fanout'})) {
- push @args, '-f';
- push @args, $elements{'fanout'};
- }
- if (defined($elements{'rootimg'})) {
- push @args, '-i';
- push @args, $elements{'rootimg'};
- }
- if (defined($elements{'options'})) {
- push @args, '-o';
- push @args, $elements{'options'};
- }
- if (defined($elements{'rsyncfile'})) {
- push @args, '-F';
- push @args, $elements{'rsyncfile'};
- }
- if (defined($elements{'preserve'})) {
- push @args, '-p';
- }
- if (defined($elements{'pull'})) {
- push @args, '-P';
- }
- if (defined($elements{'showconfig'})) {
- push @args, '-q';
- }
- if (defined($elements{'remotecopy'})) {
- push @args, '-r';
- push @args, $elements{'remotecopy'};
- }
- if (defined($elements{'recursive'})) {
- push @args, '-R';
- }
- if (defined($elements{'timeout'})) {
- push @args, '-t';
- push @args, $elements{'timeout'};
- }
- if (defined($elements{'source'})) {
- push @args, $elements{'source'};
- }
- if (defined($elements{'target'})) {
- push @args, $elements{'target'};
- }
- }
- }
- else {
- my %elements;
- my $name;
- my $val;
-
- $request->{command} = "tabch";
- push @args, "node=" . $request->{noderange};
-
- extractData(\%elements, @entries);
- while (($name, $val) = each (%elements)) {
- push @args, $name . "=" . $val;
- }
- }
- }
- elsif (isPost()) {
- $request->{command} = 'mkdef';
- push @args, "-t", "node";
-
- unless (defined($noderange)) {
- addPageContent("No nodename was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- push @args, "-o", $noderange;
-
- if ($q->param('POSTDATA')) {
- my $entries = JSON::decode_json($q->param('POSTDATA'));
- if (scalar($entries) < 1) {
- addPageContent("No Field and Value map was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- foreach (@$entries) {
- push @args, $_;
- }
- }
- }
- elsif (isDelete()) {
-
- #FYI: the nodeRange for delete has to be specified in the URI
- $request->{command} = 'rmdef';
- push @args, "-t", "node";
- unless (defined($noderange)) {
- addPageContent("No nodename was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- push @args, "-o", $noderange;
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- if (@envs) {
- push @{$request->{env}}, @envs;
- }
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-my @notificationFields = ('filename', 'tables', 'tableops', 'comments', 'disable');
-
-#complete, unless there is some way to alter existing notifications
-sub notificationsHandler {
- my @responses;
- my @args;
-
- #does not support using the notification fileName in the URI
-
- if (isGet()) {
- if (defined $q->param('fileName')) {
- $request->{command} = 'gettab';
- push @args, "filename" . $q->param('fileName');
-
- #if they specified the fields, just get those
- if (defined $q->param('field')) {
- foreach ($q->param('field')) {
- push @args, $_;
- }
- }
-
- #else show all of the fields
- else {
- foreach (@notificationFields) {
- push @args, "notification.$_";
- }
- }
- }
- else {
- $request->{command} = 'tabdump';
- push @args, "notification";
- }
- }
- elsif (isPost()) {
- $request->{command} = 'regnotif';
- if (!defined $q->param('fileName') || !defined $q->param('table') || !defined $q->param('operation')) {
- addPageContent("fileName, table and operation must be specified for a POST on /notifications");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- else {
- push @args, $q->param('fileName');
- my $tables;
- foreach ($q->param('table')) {
- $tables .= "$_,";
- }
-
- #get rid of the extra comma
- chop($tables);
- push @args, $tables;
- push @args, '-o';
- my $operations;
- foreach ($q->param('operation')) {
- $operations .= "$_,";
- }
-
- #get rid of the extra comma
- chop($operations);
- push @args, $q->param('operation');
- }
- }
- elsif (isDelete()) {
- $request->{command} = 'unregnotif';
- if (defined $q->param('fileName')) {
- push @args, $q->param('fileName');
- }
- else {
- addPageContent("fileName must be specified for a DELETE on /notifications");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- addPageContent("request is " . Dumper($request));
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-my @policyFields =
- ('priority', 'name', 'host', 'commands', 'noderange', 'parameters', 'time', 'rule', 'comments', 'disable');
-
-#complete
-sub policiesHandler {
- my @responses;
- my @args;
- my $priority;
-
- #does it specify the prioirty in the URI?
- if (defined $path[1]) {
- $priority = $path[1];
- }
-
- #in the query string?
- elsif (defined $q->param('priority')) {
- $priority = $q->param('priority');
- }
-
- if (isGet()) {
- if (defined $priority) {
- $request->{command} = 'gettab';
- push @args, "priority=$priority";
- my @fields = $q->param('field');
-
- #if they specified fields to retrieve
- if (@fields) {
- push @args, @fields;
- }
-
- #give them everything if nothing is specified
- else {
- foreach (@policyFields) {
- push @args, "policy.$_";
- }
- }
- }
- else {
- $request->{command} = 'tabdump';
- push @args, 'policy';
- }
- }
- elsif (isPost()) {
- if (defined $priority) {
- $request->{command} = 'tabch';
- push @args, "priority=$priority";
- for ($q->param) {
- if ($_ ne /priority/) {
- push @args, "policy.$_=" . $q->param($_);
- }
- }
- }
-
- #some response about the priority being required
- else {
- addPageContent("The priority must be specified when creating a policy");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif (isDelete()) {
-
- #just allowing a delete by priority at the moment, could expand this to anything
- if (defined $priority) {
- $request->{command} = 'tabch';
- push @args, '-d';
- push @args, "priority=$priority";
- push @args, "policy";
- }
- }
- elsif (isPut() || isPatch()) {
- if (defined $priority) {
- $request->{command} = 'tabch';
- push @args, "priority=$priority";
- for ($q->param) {
- if ($_ ne /priority/) {
- push @args, "policy.$_=" . $q->param($_);
- }
- }
- }
-
- #some response about the priority being required
- else {
- addPageContent("The priority must be specified when updating a policy");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- addPageContent("request is " . Dumper($request));
- my $req = genRequest();
- @responses = sendRequest($req);
-
- return @responses;
-}
-
-#complete
-sub siteHandler {
- my @data;
- my @responses;
- my @args;
-
- if (isGet()) {
- $request->{command} = 'lsdef';
- push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite';
- my @temparray = $q->param('field');
-
- #add the field name to get
- if (scalar(@temparray) > 0) {
- push @{$request->{arg}}, '-i';
- push @{$request->{arg}}, join(',', @temparray);
- }
- }
- elsif (isPut()) {
- $request->{command} = 'chdef';
- push @{$request->{arg}}, '-t', 'site', '-o', 'clustersite';
- 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'}}) {
- my ($key, $value) = split(/=/, $put, 2);
- if ($key eq 'field' && $value) {
- push @{$request->{arg}}, $value;
- }
- }
- }
- } else {
- if ($q->param('PUTDATA')) {
- my $entries = JSON::decode_json($q->param('PUTDATA'));
- foreach (@$entries) {
- push @{$request->{arg}}, $_;
- }
- }
- else {
- addPageContent("No Field and Value map was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- }
- else {
- unsupportedRequestType();
- }
-
- my $req = genRequest();
- @responses = sendRequest($req);
- return @responses;
-}
-
-my $formatType;
-
-#provide direct table access
-#complete and tested on the site table
-#use of the actual DELETE doesn't seem to fit here, since a resource would not be deleted
-#using PUT or PATCH instead, though it doesn't feel all that correct either
-sub tablesHandler {
- my @responses;
- my $table;
- my @args;
-
- #is the table name specified in the URI?
- if (defined $path[1]) {
- $table = $path[1];
- }
-
- #handle all gets
- if (isGet()) {
-
- #table was specified
- if (defined $table) {
- if (defined($q->param('col'))) {
- $request->{command} = 'gettab';
- push @args, $q->param('col') . '=' . $q->param('value');
- my @temparray = $q->param('attribute');
- foreach (@temparray) {
- push @args, $table . '.' . $_;
- }
- }
- else {
- $request->{command} = 'tabdump';
- push @args, $table;
- if (!defined $q->param('desc')) {
- $formatType = 'splitCommas';
- }
- }
- }
- else {
- $request->{command} = 'tabdump';
- }
- }
- elsif (isPut() || isPatch()) {
- my $condition = $q->param('condition');
- my @vals;
- my $entries;
- if (!defined $condition) {
- unless ($q->param('PUTDATA')) {
- foreach my $put (@{$queryhash{'putData'}}) {
- my ($key, $value) = split(/=/, $put, 2);
- if ($key eq 'condition' && $value) {
- $condition = $value;
- }
- }
- foreach my $put (@{$queryhash{'putData'}}) {
- my ($key, $value) = split(/=/, $put, 2);
- if ($key eq 'value') {
- push(@vals, $value);
- }
- }
- }
- else {
- $entries = JSON::decode_json($q->param('PUTDATA'));
- if (scalar(@$entries) < 1) {
- addPageContent("No set attribute was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- }
-
- if (!defined $table || !defined $condition) {
- if (scalar(@$entries) < 1) {
- addPageContent("The table and condition must be specified when adding, changing or deleting an entry");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- $request->{command} = 'tabch';
- my $del;
- if (!defined $q->param('delete')) {
- foreach my $put (@{$queryhash{'putData'}}) {
- my ($key, $value) = split(/=/, $put, 2);
- if ($key eq 'delete') {
- $del = 1;
- }
- }
- }
-
- if (defined $q->param('delete') || defined $del) {
- push @args, '-d';
- push @args, $condition;
- push @args, $table;
- }
- elsif (defined $condition) {
- push @args, $condition;
- if ($q->param('value')) {
- for ($q->param('value')) {
- push @args, "$table.$_";
- }
- }
- else {
- @args = (@args, @vals);
- }
- }
- else {
- foreach (@$entries) {
- push @args, split(/ /,$_);
- }
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
- return @responses;
-}
-
-my @accountFields = ('key', 'username', 'password', 'cryptmethod', 'comments', 'disable');
-
-#done aside from being able to change cluster users, which xcat can't do yet
-sub accountsHandler {
- my @responses;
- my @args;
- my $key = $q->param('key');
-
- if (isGet()) {
-
- #passwd table
- if (!defined $q->param('clusterUser')) {
- if (defined $key) {
- $request->{command} = 'gettab';
- push @args, "key=$key";
- if (defined $q->param('field')) {
- foreach ($q->param('field')) {
- push @args, "passwd.$_";
- }
- }
- else {
- foreach (@accountFields) {
- push @args, "passwd.$_";
- }
- }
- }
- else {
- $request->{command} = 'tabdump';
- push @args, 'passwd';
- }
- }
-
- #cluster user list
- else {
- $request->{command} = 'xcatclientnnr';
- push @args, 'clusteruserlist';
- push @args, '-p';
- }
- }
- elsif (isPost()) {
- if (!defined $q->param('clusterUser')) {
- if (defined $key) {
- $request->{command} = 'tabch';
- push @args, "key=$key";
- for ($q->param) {
- if ($_ !~ /key/) {
- push @args, "passwd.$_=" . $q->param($_);
- }
- }
- }
- else {
- addPageContent("The key must be specified when creating a non-cluster user");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
-
- #active directory user
- else {
- if (defined $q->param('userName') && defined $q->param('userPass')) {
- $request->{command} = 'xcatclientnnr';
- push @args, 'clusteruseradd';
- push @args, $q->param('userName');
- push @{$request->{arg}}, @args;
- $request->{environment} = {XCAT_USERPASS => $q->param('userPass')};
- }
- else {
- addPageContent("The key must be specified when creating a cluster user");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- }
- elsif (isDelete()) {
- if (!defined $q->param('clusterUser')) {
-
- #just allowing a delete by key at the moment, could expand this to anything
- if (defined $key) {
- $request->{command} = 'tabch';
- push @args, '-d';
- push @args, "key=$key";
- push @args, "passwd";
- }
- else {
- addPageContent("The key must be specified when deleting a non-cluster user");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- else {
- if (defined $q->param('userName')) {
- $request->{command} = 'xcatclientnnr';
- push @args, 'clusteruserdel';
- push @args, $q->param('userName');
- }
- else {
- addPageContent("The userName must be specified when deleting a cluster user");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- }
- elsif (isPut() || isPatch()) {
- if (!defined $q->param('clusterUser')) {
- if (defined $key) {
- $request->{command} = 'tabch';
- push @args, "key=$key";
- for ($q->param) {
- if ($_ !~ /key/) {
- push @args, "passwd.$_=" . $q->param($_);
- }
- }
- }
- else {
- addPageContent("The key must be specified when updating a non-cluster user");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
-
- #TODO: there isn't currently a way to update cluster users
- else {
-
- }
- }
- else {
- unsupportedRequestType();
- exit(0);
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
- return @responses;
-}
-
-sub objectsHandler {
- my @responses;
- my @args;
- my @objectTypeList = (
- "auditlog", "boottarget", "eventlog", "firmware", "group", "monitoring",
- "network", "node", "notification", "osimage", "policy", "route",
- "site");
-
- #my %objectTypes;
- #foreach my $item (@objectTypeList) { $objectTypes{$item} = 1 }
- my @objectTypes;
- my @objects;
- if (defined $path[1]) {
- $objectTypes[0] = $path[1];
- if (defined $path[2]) {
- $objects[0] = $path[2];
- }
- }
- if (defined $q->param('objectType')) {
- @objectTypes = $q->param('objectType');
- }
- if (defined $q->param('object')) {
- @objects = $q->param('object');
- }
-
- if ($q->param('verbose')) {
- push @args, '-v';
- }
-
- if (isGet()) {
- if (defined $objectTypes[0]) {
- $request->{command} = 'lsdef';
- push @args, '-l';
- push @args, '-t';
- push @args, join(',', @objectTypes);
- if (defined $objects[0]) {
- push @args, '-o';
- push @args, join(',', @objects);
- }
- if ($q->param('info')) {
- push @args, '-h';
- }
- }
- else {
- if ($q->param('info')) {
- push @args, '-h';
- }
- else {
-
- #couldn't find a way to do this through xcatd, so shortcutting the request
- my %resp = (data => \@objectTypeList);
- return (\%resp);
- }
- }
- }
- elsif (isPut()) {
- $request->{command} = 'chdef';
- if ($q->param('verbose')) {
- push @args, '-v';
- }
- if (!defined $q->param('objectType')) {
- addPageContent("The object must be specified.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- else {
- push @args, '-t';
- push @args, join(',', $q->param('objectType'));
- }
- if ($q->param('objectName')) {
- push @args, join(',', $q->param('objectName'));
- }
- if ($q->param('dynamic')) {
- push @args, '-d';
- }
- if ($q->param('minus')) {
- push @args, '-m';
- }
- if ($q->param('plus')) {
- push @args, '-p';
- }
- if (defined $q->param('field')) {
- foreach ($q->param('field')) {
-
- #if it has ==, !=. =~ or !~ operators in the field, use the -w option
- if (/==|!=|=~|!~/) {
- push @args, '-w';
- }
- push @args, $_;
- }
- }
- if ($q->param('nodeRange')) {
- push @args, $q->param('nodeRange');
- }
-
- }
- elsif (isPost()) {
- $request->{command} = 'mkdef';
- if ($q->param('verbose')) {
- push @args, '-v';
- }
- if (!defined $q->param('objectType')) {
- addPageContent("The object must be specified.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- else {
- push @args, '-t';
- push @args, join(',', $q->param('objectType'));
- }
- if ($q->param('objectName')) {
- push @args, join(',', $q->param('objectName'));
- }
- if ($q->param('dynamic')) {
- push @args, '-d';
- }
- if ($q->param('force')) {
- push @args, '-f';
- }
- if (defined $q->param('field')) {
- foreach ($q->param('field')) {
-
- #if it has ==, !=. =~ or !~ operators in the field, use the -w option
- if (/==|!=|=~|!~/) {
- push @args, '-w';
- }
- push @args, $_;
- }
- }
- if ($q->param('nodeRange')) {
- push @args, $q->param('nodeRange');
- }
-
- }
- elsif (isDelete()) {
- $request->{command} = 'rmdef';
- if (defined $q->param('info')) {
- push @args, '-h';
- }
- elsif (defined $q->param('all')) {
- push @args, '-a';
- }
- elsif (defined $objectTypes[0]) {
- push @args, '-t';
- push @args, join(',', @objectTypes);
- if (defined $objects[0]) {
- push @args, '-o';
- push @args, join(',', @objects);
- }
- }
- else {
- addPageContent(
-"Either the help info must be requested or the object must be specified or the flag that indicates everything should be removed."
- );
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- if (defined $q->param('nodeRange')) {
- push @args, $q->param('nodeRange');
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
- return @responses;
-}
-
-#complete i think, tho chvm could handle args better
-sub vmsHandler {
- my @args;
- my $noderange;
- my $subResource;
- if (defined $path[1]) {
- $noderange = $path[1];
- $request->{noderange} = $noderange;
- }
- else {
- addPageContent("Invalid nodes and/or groups in noderange");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (isGet()) {
- $request->{command} = 'lsvm';
- if (defined $q->param('all')) {
- push @args, '-a';
- }
-
- # for z/VM
- if (defined $q->param('networknames')) {
- push @args, '--getnetworknames';
- }
-
- if (defined $q->param('network')) {
- push @args, '--getnetwork';
- push @args, $q->param('getnetwork');
- }
-
- if (defined $q->param('diskpoolnames')) {
- push @args, '--diskpoolnames';
- }
-
- if (defined $q->param('diskpool')) {
- push @args, '--diskpool';
- push @args, $q->param('diskpool');
- }
-
- if (defined $q->param('checknics')) {
- push @args, '--checknics';
- push @args, $q->param('checknics');
- }
- }
- elsif (isPost()) {
- my $entries;
- my %entryhash;
- my $position;
- $request->{command} = 'mkvm';
- unless ($q->param('POSTDATA')) {
- addPageContent("Invalid Parameters");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- #collect all parameters from the postdata
- $entries = JSON::decode_json($q->param('POSTDATA'));
- if (scalar(@$entries) < 1) {
- addPageContent("No set attribute was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- extractData(\%entryhash, $entries);
-
- # For zVM; clonefrom must be first so that the mkvm call
- # has the clone from node in correct spot in makeVM args
- if (defined $entryhash{'clonefrom'}) {
- push @args, $entryhash{'clonefrom'};
- }
-
- #for system p
- if (defined $entryhash{'cec'}) {
- push @args, '-c';
- push @args, $entryhash{'cec'};
- }
-
- if (defined $entryhash{'startId'}) {
- push @args, '-i';
- push @args, $entryhash{'startId'};
- }
-
- if (defined $entryhash{'source'}) {
- push @args, '-l';
- push @args, $entryhash{'source'};
- }
-
- if (defined $entryhash{'profile'}) {
- push @args, '-p';
- push @args, $entryhash{'profile'};
- }
-
- if (defined $entryhash{'full'}) {
- push @args, '--full';
- }
-
- #for KVM & Vmware
- if (defined $entryhash{'master'}) {
- push @args, '-m';
- push @args, $entryhash{'master'};
- }
-
- if (defined $entryhash{'disksize'}) {
- push @args, '-s';
- push @args, $entryhash{'disksize'};
- }
-
- if (defined $entryhash{'memory'}) {
- push @args, '--mem';
- push @args, $entryhash{'memory'};
- }
-
- if (defined $entryhash{'cpu'}) {
- push @args, '--cpus';
- push @args, $entryhash{'cpu'};
- }
-
- if (defined $entryhash{'force'}) {
- push @args, '-f';
- }
-
- # for z/VM
- if (defined $entryhash{'userid'}) {
- push @args, '--userid';
- push @args, $entryhash{'userid'};
- }
-
- if (defined $entryhash{'size'}) {
- push @args, '--size';
- push @args, $entryhash{'size'};
- }
-
- if (defined $entryhash{'password'}) {
- push @args, '--password';
- push @args, $entryhash{'password'};
- }
-
- if (defined $entryhash{'privilege'}) {
- push @args, '--privilege';
- push @args, $entryhash{'privilege'};
- }
-
- if (defined $entryhash{'diskpool'}) {
- push @args, '--diskpool';
- push @args, $entryhash{'diskpool'};
- }
-
- if (defined $entryhash{'diskvdev'}) {
- push @args, '--diskVdev';
- push @args, $entryhash{'diskvdev'};
- }
- if (defined $entryhash{'imagename'}) {
- push @args, '--imagename';
- push @args, $entryhash{'imagename'};
- }
- if (defined $entryhash{'osimage'}) {
- push @args, '--osimage';
- push @args, $entryhash{'osimage'};
- }
- if (defined $entryhash{'ipl'}) {
- push @args, '--ipl';
- push @args, $entryhash{'ipl'};
- }
- # For the mkvm call the zvm.pm code is looking for key=value
- # for pool and pw; rather than a "--key value"
- if ( defined $entryhash{'pool'} ) {
- push @args, "pool=$entryhash{'pool'}";
- }
- if ( defined $entryhash{'pw'} ) {
- push @args, "pw=$entryhash{'pw'}";
- }
- }
- elsif (isPut()) {
- $request->{command} = 'chvm';
- if ($q->param('PUTDATA')) {
- my $entries = JSON::decode_json($q->param('PUTDATA'));
- if (scalar(@$entries) < 1) {
- addPageContent("No Field and Value map was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- foreach (@$entries) {
- # Handle blank delimited parameters
- push @args, split(/ /,$_);
- }
- }
- else {
- addPageContent("No Field and Value map was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
- }
- elsif (isDelete()) {
- $request->{command} = 'rmvm';
- if (defined $q->param('retain')) {
- push @args, '-r';
- }
- if (defined $q->param('service')) {
- push @args, '--service';
- }
- }
- else {
- unsupportedRequestType();
- exit();
- }
-
- # Note: MUST parse these parameters after all others if we want to avoid
- # duplicating this code on each if branch, since
- # lsvm depends on its "subcommand" being the first parameter.
- # TODO if we add these parameters to other paths, could we use a subroutine instead? only 2 inputs.
-
- # Parse the optional upstream object ID, e.g. an OpenStack nova instance UUID
- if (defined $queryhash{'objectid'}) {
- push @args, '--objectid';
- push @args, $queryhash{'objectid'}->[0];
- }
-
- # Parse the optional upstream request ID, e.g. an OpenStack request UUID
- if (defined $queryhash{'requestid'}) {
- push @args, '--requestid';
- push @args, $queryhash{'requestid'}->[0];
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- my @responses = sendRequest($req);
- return @responses;
-}
-
-sub versionHandler {
- $request->{command} = "lsxcatd";
- push @{$request->{arg}}, "-v";
- my $req = genRequest();
- my @responses = sendRequest($req);
- return @responses;
-}
-
-#for operations that take a 'long' time to finish, this will provide the interface to check their status
-sub jobsHandler {
-
-}
-
-sub hypervisorHandler {
- my @responses;
- my @args;
- if (isPut()) {
- my %entryhash;
- if (defined $path[1]) {
- $request->{noderange} = $path[1];
- }
- else {
- addPageContent("Invalid nodes and/or groups in node in noderange");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- if (defined $path[2]) {
- $request->{command} = $path[2];
- }
- else {
- $request->{command} = 'chhypervisor';
- }
- my $entries = JSON::decode_json( $q->param('PUTDATA') );
- if (scalar(@$entries) < 1) {
- addPageContent("No set attribute was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- foreach (@$entries) {
- push @args, split(/ /,$_);
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
- return @responses;
- }
-}
-
-sub debugHandler {
- my @responses;
- my @args;
- if (isPut()) {
- my %entryhash;
- $request->{command} = 'xcatclientnnr xcatdebug';
-
- #push @args, 'xcatdebug';
- my $entries = JSON::decode_json( $q->param('PUTDATA') );
- if (scalar(@$entries) < 1) {
- addPageContent("No set attribute was supplied.");
- sendResponseMsg($STATUS_BAD_REQUEST);
- }
-
- foreach (@$entries) {
- push @{$request->{arg}}, $_;
- }
-
- push @{$request->{arg}}, @args;
- my $req = genRequest();
- @responses = sendRequest($req);
- return @responses;
- }
-}
-
-#all data wrapping and writing is funneled through here
-sub wrapData {
- my $data = shift;
- my $errorInformation = '';
-
- #trim the serverdone message off
- if (exists $data->[0]->{serverdone} && exists $data->[0]->{error}) {
- $errorInformation = $data->[0]->{error}->[0];
- addPageContent($q->p($errorInformation));
- if (($errorInformation =~ /Permission denied/) || ($errorInformation =~ /Authentication failure/)) {
- sendResponseMsg($STATUS_UNAUTH);
- }
- else {
- sendResponseMsg($STATUS_FORBIDDEN);
- }
- exit 1;
- }
- else {
- pop @{$data};
- }
- if (exists $formatters{$format}) {
- $formatters{$format}->($data);
- }
-
- #all information were add into the global varibale, call the response funcion
- if (exists $data->[0]->{info} && $data->[0]->{info}->[0] =~ /Could not find an object/) {
- sendResponseMsg($STATUS_NOT_FOUND);
- }
- elsif (isPost()) {
- sendResponseMsg($STATUS_CREATED);
- }
- else {
- sendResponseMsg($STATUS_OK);
- }
-}
-
-sub wrapJson {
- my $data = shift;
- my $json;
- $json->{'data'} = $data;
- addPageContent(JSON::to_json($json));
-}
-
-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("
");
- foreach $item (@{$element->{node}}) {
-
- #my $url = $baseUri.$item->{name}[0];
- addPageContent("$item->{name}[0] | ");
- if (exists $item->{data} && exists $item->{data}[0]) {
- if (ref($item->{data}[0]) eq 'HASH') {
- if (exists $item->{data}[0]->{desc} && exists $item->{data}[0]->{desc}[0]) {
- addPageContent("$item->{data}[0]->{desc}[0] | ");
- }
- if (ref($item->{data}[0]) eq 'HASH' && exists $item->{data}[0]->{contents}[0]) {
- addPageContent("$item->{data}[0]->{contents}[0] | ");
- }
- }
- else {
- addPageContent("$item->{data}[0] | ");
- }
- }
- elsif (exists $item->{error}) {
- addPageContent("$item->{error}[0] | ");
- }
- addPageContent("
");
- }
- addPageContent("
");
- }
- if ($element->{data}) {
- addPageContent("");
- foreach $item (@{$element->{data}}) {
- my @values = split(/:/, $item, 2);
- addPageContent("");
- foreach (@values) {
- if ($formatType =~ /splitCommas/) {
- my @fields = split(/,/, $_, -1);
- foreach (@fields) {
- addPageContent("$_ | ");
- }
- }
- else {
- addPageContent("$_ | ");
- }
- }
- addPageContent("
\n");
- }
- addPageContent("
");
- }
- if ($element->{info}) {
- addPageContent("");
- foreach $item (@{$element->{info}}) {
- addPageContent("");
- my $fieldname = '';
- my $fieldvalue = '';
-
- #strip whitespace in the string
- $item =~ s/^\s+//;
- $item =~ s/\s+$//;
- if ($item =~ /Object/) {
- ($fieldname, $fieldvalue) = split(/:/, $item);
- }
- elsif ($item =~ /.*=.*/) {
- my $position = index $item, '=';
- $fieldname = substr $item, 0, $position;
- $fieldvalue = substr $item, $position + 1;
- }
- else {
- $fieldname = $item;
- }
- addPageContent("" . $fieldname . " | ");
- if ($fieldvalue ne '') {
- addPageContent("" . $fieldvalue . " | ");
- }
- addPageContent("
\n");
- }
- addPageContent("
");
- }
- if ($element->{error}) {
- addPageContent("");
- foreach $item (@{$element->{error}}) {
- addPageContent("" . $item . " |
");
- }
- addPageContent("
");
- }
- }
-}
-
-sub wrapXml {
- my @data = shift;
- foreach (@data) {
- foreach (@$_) {
- addPageContent(XMLout($_, RootName => '', NoAttr => 1, KeyAttr => []));
- }
- }
-}
-
-#general tests for valid requests and responses with HTTP codes here
-if (!doesResourceExist($resource)) {
- addPageContent("Resource '$resource' does not exist");
- sendResponseMsg($STATUS_NOT_FOUND);
-}
-else {
- if ($DEBUGGING) {
- addPageContent($q->p("resource is $resource"));
- }
- handleRequest();
-}
-
-#talk to the server
-use Socket;
-use IO::Socket::INET;
-use IO::Socket::SSL;
-
-# The database initialization may take some time in the system boot scenario
-# wait for a while for the database initialization
-#do we really need to do this for the web service?
-sub sendRequest {
- my $request = shift;
- my $sitetab;
- my $retries = 0;
-
- if ($DEBUGGING) {
- my $preXml = $request;
-
- #$preXml =~ s/
< /g;
- #$preXml =~ s/>/>
/g;
- addPageContent($q->p("request XML
" . $preXml));
- }
-
- #hardcoded port for now
- my $port = 3001;
- my $xcatHost = "localhost:$port";
-
- #temporary, will be using username and password
- my $homedir = "/root";
- my $keyfile = $homedir . "/.xcat/client-cred.pem";
- my $certfile = $homedir . "/.xcat/client-cred.pem";
- my $cafile = $homedir . "/.xcat/ca.pem";
-
- my $client;
- if (-r $keyfile and -r $certfile and -r $cafile) {
- $client = IO::Socket::SSL->new(
- PeerAddr => $xcatHost,
- SSL_key_file => $keyfile,
- SSL_cert_file => $certfile,
- SSL_ca_file => $cafile,
- SSL_use_cert => 1,
- Timeout => 15,);
- }
- else {
- $client = IO::Socket::SSL->new(
- PeerAddr => $xcatHost,
- SSL_verify_mode => 'SSL_VERIFY_NONE',
- Timeout => 15,);
- }
- unless ($client) {
- if ($@ =~ /SSL Timeout/) {
- addPageContent("Connection failure: SSL Timeout or incorrect certificates in ~/.xcat");
- sendResponseMsg($STATUS_TIMEOUT);
- }
- else {
- addPageContent("Connection failurexx: $@");
- sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
- }
- }
-
- print $client $request;
-
- my $response;
- my $rsp;
- my @fullResponse;
- my $cleanexit = 0;
- while (<$client>) {
- $response .= $_;
- if (m/<\/xcatresponse>/) {
-
- #replace ESC with xxxxESCxxx because XMLin cannot handle it
- if ($DEBUGGING) {
- addPageContent($response . "\n");
- }
- $response =~ s/\e/xxxxESCxxxx/g;
-
- #print "responseXML is ".$response;
- $rsp = XMLin($response, SuppressEmpty => undef, ForceArray => 1);
-
- #add ESC back
- foreach my $key (keys %$rsp) {
- if (ref($rsp->{$key}) eq 'ARRAY') {
- foreach my $text (@{$rsp->{$key}}) {
- next unless defined $text;
- $text =~ s/xxxxESCxxxx/\e/g;
- }
- }
- else {
- $rsp->{$key} =~ s/xxxxESCxxxx/\e/g;
- }
- }
-
- $response = '';
- push(@fullResponse, $rsp);
- if ($rsp->{serverdone}) {
- $cleanexit = 1;
- last;
- }
- }
- }
- unless ($cleanexit) {
- addPageContent("ERROR/WARNING: communication with the xCAT server seems to have been ended prematurely");
- sendResponseMsg($STATUS_SERVICE_UNAVAILABLE);
- exit(0);
- }
-
- if ($DEBUGGING) {
- addPageContent($q->p("response " . Dumper(@fullResponse)));
- }
- return @fullResponse;
-}
-
-sub isGet {
- return uc($requestType) eq "GET";
-}
-
-sub isPut {
- return uc($requestType) eq "PUT";
-}
-
-sub isPost {
- return uc($requestType) eq "POST";
-}
-
-sub isPatch {
- return uc($requestType) eq "PATCH";
-}
-
-sub isDelete {
- return uc($requestType) eq "DELETE";
-}
-
-#check to see if this is a valid user. userName and password are already set
-sub isAuthenticUser {
- $request->{command} = 'authcheck';
- my $req = genRequest();
- my @responses = sendRequest($req);
- if ($responses[0]->{data}[0] eq "Authenticated") {
-
- #user is authenticated
- return 1;
- }
-
- #authentication failure
- addPageContent($responses[0]->{error}[0]);
- sendResponseMsg($STATUS_UNAUTH);
-}