2
0
mirror of https://github.com/xcat2/xcat-core.git synced 2025-06-13 01:40:26 +00:00

Merge pull request #5116 from gurevichmark/rest_api_token_expire

Token expiration setting
This commit is contained in:
Yuan Bai
2018-04-23 10:40:22 +08:00
committed by GitHub
14 changed files with 243 additions and 516 deletions

View File

@ -58,7 +58,15 @@ Then in the subsequent REST API access, the token can be used to replace the use
curl -X GET -k -H X-Auth-Token:5cabd675-bc2e-4318-b1d6-831fd1f32f97 'https://<FQDN of xCAT MN>/xcatws/<resource>?<parameters>
The validity of token is 24 hours. If an old token has expired, you will get a 'Authentication failure' error. Then you need reacquire a token with your account.
The default validity of a token is 1 day. This default can be changed by the setting of `tokenexpiredays` attribute in `site` table. ::
chdef -t site clustersite tokenexpiredays=<days>
To make tokens valid forever use "never". ::
chdef -t site clustersite tokenexpiredays=never
If an old token has expired, you will get a 'Authentication failure' error. You will need to reacquire a token for your account.
The Common Parameters for Resource URI

View File

@ -229,9 +229,10 @@ For example, to run rscan command against the hardware control point of compute
.. code-block:: perl
rscan __GETNODEATTR($$CN, hcp)__ -z
3. B<GETTABLEVALUE(keyname, key, colname, table)> To get the value of column where keyname == key in specified table.
3. \ **GETTABLEVALUE(keyname, key, colname, table)**\ To get the value of column where keyname == key in specified table.
*****
FILES

View File

@ -80,7 +80,7 @@ policy Attributes:
\ **rule**\
Specifies how this rule should be applied. Valid values are: allow, accept, trusted. Allow or accept will allow the user to run the commands. Any other value will deny the user access to the commands. Trusted means that once this client has been authenticated via the certificate, all other information that is sent (e.g. the username) is believed without question. This authorization should only be given to the xcatd on the management node at this time.
Specifies how this rule should be applied. Valid values are: allow, trusted. Allow will allow the user to run the commands. Any other value will deny the user access to the commands. Trusted means that once this client has been authenticated via the certificate, all other information that is sent (e.g. the username) is believed without question. This authorization should only be given to the xcatd on the management node at this time.

View File

@ -429,6 +429,8 @@ site Attributes:
--------------------
XCAT DAEMON ATTRIBUTES
--------------------
tokenexpiredays: Number of days before REST API token will expire. The default is 1.
use 'never' if you want your token to never expire.
useflowcontrol: (yes/1 or no/0). If yes, the postscript processing on each node
contacts xcatd on the MN/SN using a lightweight UDP packet to wait
until xcatd is ready to handle the requests associated with

View File

@ -19,7 +19,7 @@ SYNOPSIS
********
\ **token Attributes:**\ \ *tokenid*\ , \ *username*\ , \ *expire*\ , \ *comments*\ , \ *disable*\
\ **token Attributes:**\ \ *tokenid*\ , \ *username*\ , \ *expire*\ , \ *created*\ , \ *access*\ , \ *comments*\ , \ *disable*\
***********
@ -54,6 +54,18 @@ token Attributes:
\ **created**\
Creation time for this token.
\ **access**\
Last access time for this token.
\ **comments**\
Any user-provided notes.

View File

@ -77,7 +77,7 @@ policy Attributes:
\ **rule**\ (policy.rule)
Specifies how this rule should be applied. Valid values are: allow, accept, trusted. Allow or accept will allow the user to run the commands. Any other value will deny the user access to the commands. Trusted means that once this client has been authenticated via the certificate, all other information that is sent (e.g. the username) is believed without question. This authorization should only be given to the xcatd on the management node at this time.
Specifies how this rule should be applied. Valid values are: allow, trusted. Allow will allow the user to run the commands. Any other value will deny the user access to the commands. Trusted means that once this client has been authenticated via the certificate, all other information that is sent (e.g. the username) is believed without question. This authorization should only be given to the xcatd on the management node at this time.

View File

@ -890,7 +890,7 @@ passed as argument rather than by table value',
noderange => 'The Noderange that this rule applies to. Default is "*" (all nodes). Not supported with the *def commands.',
parameters => 'A regular expression that matches the command parameters (everything except the noderange) that this rule applies to. Default is "*" (all parameters). Not supported with the *def commands.',
time => 'Time ranges that this command may be executed in. This is not supported.',
rule => 'Specifies how this rule should be applied. Valid values are: allow, accept, trusted. Allow or accept will allow the user to run the commands. Any other value will deny the user access to the commands. Trusted means that once this client has been authenticated via the certificate, all other information that is sent (e.g. the username) is believed without question. This authorization should only be given to the xcatd on the management node at this time.',
rule => 'Specifies how this rule should be applied. Valid values are: allow, trusted. Allow will allow the user to run the commands. Any other value will deny the user access to the commands. Trusted means that once this client has been authenticated via the certificate, all other information that is sent (e.g. the username) is believed without question. This authorization should only be given to the xcatd on the management node at this time.',
comments => 'Any user-written notes.',
disable => "Set to 'yes' or '1' to comment out this row.",
},
@ -1285,6 +1285,8 @@ passed as argument rather than by table value',
" --------------------\n" .
"XCAT DAEMON ATTRIBUTES\n" .
" --------------------\n" .
" tokenexpiredays: Number of days before REST API token will expire. The default is 1.\n" .
" use 'never' if you want your token to never expire.\n" .
" useflowcontrol: (yes/1 or no/0). If yes, the postscript processing on each node\n" .
" contacts xcatd on the MN/SN using a lightweight UDP packet to wait\n" .
" until xcatd is ready to handle the requests associated with\n" .
@ -1802,13 +1804,15 @@ zvmivp => {
},
},
token => {
cols => [qw(tokenid username expire comments disable)],
cols => [qw(tokenid username expire created access comments disable)],
keys => [qw(tokenid)],
table_desc => 'The token of users for authentication.',
descriptions => {
tokenid => 'It is a UUID as an unified identify for the user.',
username => 'The user name.',
expire => 'The expire time for this token.',
created => 'Creation time for this token.',
access => 'Last access time for this token.',
comments => 'Any user-provided notes.',
disable => "Set to 'yes' or '1' to comment out this row.",
},

View File

@ -3894,6 +3894,42 @@ sub gettimezone
#--------------------------------------------------------------------------------
=head3 time2string
Return passed in time (in DateTime format) as a string in YYYY/MM/DD HH:MM:SS format
Arguments:
Unix DateTime as returned by time() for example
Optional Separator character for date, default is "/"
Returns:
String in YYYY/MM/DD HH:MM:SS format
Globals:
none
Error:
None
Example:
my $time_string = xCAT::Utils->time2string($time,"-");
Comments:
none
=cut
#--------------------------------------------------------------------------------
sub time2string
{
my $unixtime = shift;
my $date_separator;
if ($unixtime =~ /xCAT::Utils/)
{
$unixtime = shift;
$date_separator = shift // "/"; # Optional date separator, if not specified, default to "/"
}
my $time_separator = ":";
my ($sec, $min, $hour, $mday, $mon, $year) = localtime($unixtime);
$year += 1900;
$mon += 1;
return $year . $date_separator . $mon . $date_separator . $mday . " " . $hour . $time_separator . $min . $time_separator . $sec;
}
#--------------------------------------------------------------------------------
=head3 specialservicemgr
some special services cannot be processed in sysVinit, upstart and systemd framework, should be process here...
Arguments:

View File

@ -7,11 +7,14 @@ BEGIN
$::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : -d '/opt/xcat' ? '/opt/xcat' : '/usr';
}
use strict;
use Date::Parse;
use xCAT::Table;
use xCAT::TableUtils;
use xCAT::MsgUtils;
use Data::Dumper;
use xCAT::NodeRange;
use xCAT::Utils;
use Scalar::Util qw/looks_like_number/;
#--------------------------------------------------------------------------------
@ -351,36 +354,66 @@ sub validate {
return 0;
}
my $tokentimeout = 86400; # one day
my $one_day = 86400; # one day in seconds
my $days = 1; # default days for token expiration
my $never_label = "never";
# this subroutine search the token table
# 1. find the existed token entry for the user and reset the expire time
# 1.1. if not find existed token, create a new one and add it to token table
# 2. clean up the expired token
# this subroutine creates a new token in token table
# 1. If old style unix DateTime format token found in the token table
# if expired -> remove it
# if not expired -> replace unix DateTime expiration with new human readable format
# 2. create a new token and add it to token table
#
# this subroutine is called after the account has been authorized
sub gettoken {
my $class = shift;
my $req = shift;
my $current_time = time();
my $user = $req->{gettoken}->[0]->{username}->[0];
my $tokentb = xCAT::Table->new('token');
unless ($tokentb) {
return undef;
}
my $tokens = $tokentb->getAllEntries;
# Search for "old" style tokens containing unix DateTime format expiration date
foreach my $token (@{$tokens}) {
#clean the expired token
if ($token->{'expire'} < time()) {
$tokentb->delEntries({ 'tokenid' => $token->{tokenid} });
if ($token->{'expire'} and looks_like_number($token->{'expire'})) {
# Expiration field contains only digits -> this is a old style token with unix DateTime format
if ($token->{'expire'} and ($token->{'expire'} < $current_time)) {
# Clean expired token with old unix DateTime format
$tokentb->delEntries({ tokenid => $token->{tokenid} });
} else {
# Change non-expired old style token to new human readable format
$tokentb->setAttribs({ tokenid => $token->{tokenid}, username => $token->{'username'} }, {expire => xCAT::Utils->time2string($token->{'expire'}, "-")});
}
}
}
# create a new token for this request
# create a new token id
my $uuid = xCAT::Utils->genUUID();
my $expiretime = time() + $tokentimeout;
$tokentb->setAttribs({ tokenid => $uuid, username => $user }, { expire => $expiretime });
# extract site table setting for number of days before token expires
my $token_days = xCAT::TableUtils->get_site_attribute("tokenexpiredays");
my $expiretime = $current_time + $one_day; # default is one day
my $expire_time_string = xCAT::Utils->time2string($expiretime, "-");
if ($token_days and (uc($token_days) eq uc($never_label))) {
# Tokens never expire
$expiretime = $never_label;
$expire_time_string = $never_label;
}
elsif ($token_days and $token_days > 0) {
# Use number of days from site table
$days = $token_days;
$expiretime = $current_time + $one_day * $days;
$expire_time_string = xCAT::Utils->time2string($expiretime, "-");
}
my $access_time_string = xCAT::Utils->time2string($current_time, "-");
# create a new token and set its expiration and creation time
$tokentb->setAttribs({ tokenid => $uuid, username => $user },
{ expire => $expire_time_string, created => $access_time_string });
$tokentb->close();
return ($uuid, $expiretime);
@ -391,6 +424,7 @@ sub verifytoken {
my $class = shift;
my $req = shift;
my $current_time = time();
my $tokenid = $req->{tokens}->[0]->{tokenid}->[0];
my $tokentb = xCAT::Table->new('token');
unless ($tokentb) {
@ -398,16 +432,32 @@ sub verifytoken {
}
my $token = $tokentb->getAttribs({ 'tokenid' => $tokenid }, ('username', 'expire'));
if (defined($token) && defined($token->{'username'}) && defined($token->{'expire'})) {
my $expiretime = time() + $tokentimeout;
if ($token->{'expire'} < time()) {
$tokentb->delEntries({ 'tokenid' => $token->{tokenid} });
return undef;
if ($token->{'expire'} and looks_like_number($token->{'expire'})) {
# Expiration field contains only digits -> this is a old style token with unix DateTime format
if ($token->{'expire'} and $token->{'expire'} < $current_time) {
# Clean expired token with old unix DateTime format
$tokentb->delEntries({ 'tokenid' => $token->{tokenid} });
return undef;
} else {
# Change non-expired old style token to new human readable format
$tokentb->setAttribs({ tokenid => $tokenid, username => $token->{'username'} },
{access => xCAT::Utils->time2string($current_time, "-"),
expire => xCAT::Utils->time2string($token->{'expire'}, "-")});
return $token->{'username'};
}
} else {
return $token->{'username'};
if ($token->{'expire'} and ($token->{'expire'} ne "never") and str2time($token->{'expire'}) < $current_time) {
# Expired new style token
return undef;
} else {
# Not expired new style token - update current access time
$tokentb->setAttribs({ tokenid => $tokenid, username => $token->{'username'} }, {access => xCAT::Utils->time2string($current_time, "-")});
return $token->{'username'};
}
}
} else {
# Token entry was not found
return undef;
}
}
1;

View File

@ -2826,11 +2826,15 @@ sub service_connection {
if ($peername) {
# for a valid account, get a token
my $htime;
my ($tokenid, $exptime) = xCAT::xcatd->gettoken($req);
my ($sec, $min, $hour, $mday, $mon, $year) = localtime($exptime);
$year += 1900;
$mon += 1;
my $htime = "$year-$mon-$mday $hour:$min:$sec";
if ($exptime eq "never") {
# If token expiration time was set to "never", return that to the user.
$htime = $exptime;
} else {
# Token expiration is a unix DateTime, convert to readable string
$htime = xCAT::Utils->time2string($exptime, "-");
}
$resp = { data => [ { token => [ { id => $tokenid, expire => $htime } ] } ] };
} else {
$resp = { error => ["Authentication failure"], errorcode => [1] };

View File

@ -1,242 +0,0 @@
start:node_post
description: node_post
cmd:restapitest -m POST -r /nodes/node1 -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
check:rc==201
end
start:node_post2
description: node_post2
cmd:restapitest -m POST -r /nodes/node1 -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
check:rc==403
cmdcheck:restapitest -o '{"errorcode":"1"}' -O ==
end
start:node_put
description: node_put
cmd:restapitest -m PUT -r /nodes/node1 -d '{"mgt":"hmc","netboot":"xnba"}'
check:rc==200
end
start:nodes_get
description: nodes_get
cmd:restapitest -m GET -r /nodes
check:rc==200
cmdcheck:restapitest -o '["node1"]' -O ==
end
start:node_get
description: node_get
cmd:restapitest -m GET -r /nodes/node1
check:rc==200
cmdcheck:restapitest -o '{"node1":{"netboot":"xnba"}}' -O ==
end
start:node_delete
description: node_delete
cmd:restapitest -m DELETE -r /nodes/node1
check:rc==200
end
start:nodes_get2
description: nodes_get2
cmd:restapitest -m GET -r /nodes
check:rc==200
cmdcheck:restapitest -o '["node1"]' -O !=
end
start:node_get2
description: node_get2
cmd:restapitest -m GET -r /nodes/node1
check:rc==403
cmdcheck:restapitest -o '{"errorcode":"1"}' -O ==
end
start:node_post3_for_get_test
description: node_post3_for_get_test
cmd:restapitest -m POST -r /nodes/node1 -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
check:rc==201
end
start:node_attr_get
description: node_get2
cmd:restapitest -m GET -r /nodes/node1/attrs/mgt,groups,netboot
check:rc==200
cmdcheck:restapitest -o '{"node1":{"netboot":"yaboot"}}' -O ==
end
start:node_makehosts
description: node_makehosts
cmd:restapitest -m POST -r /nodes/node1/host
check:rc==201
end
start:node_makedns
description: node_makehosts
cmd:restapitest -m POST -r /nodes/node1/dns
check:rc==201
end
start:node_delete_dns
description: node_delete_dns
cmd:restapitest -m DELETE -r /nodes/node1/dns
check:rc==200
end
start:node_put
description: node_put
cmd:restapitest -m PUT -r /nodes/node1 -d '{"mac":"00:1a:64:54:14:80"}'
check:rc==200
end
start:node_makedhcp
description: node_makedhcp
cmd:restapitest -m POST -r /nodes/node1/dhcp
check:rc==201
end
start:node_delete_dhcp
description: node_delete_dhcp
cmd:restapitest -m DELETE -r /nodes/node1/dhcp
check:rc==200
end
start:node_state
description: node_state
cmd:restapitest -m GET -r /nodes/node1/nodestat
check:rc==200
cmdcheck:restapitest -o '{"node1":{"nodestat":"ANY"}}' -O ==
end
#start:node_post4_for_scan_test
#description: node_post4_for_scan_test
#cmd:restapitest -m POST -r /nodes/e108m6hmc02 -d '{"groups":"all,hmc","mgt":"hmc","hwtype":"hmc","mtm":"7042CR4","serial":"1050FBB","nodetype":"ppc"}'
#check:rc==201
#end
start:node_scan
description: node_scan
cmd:restapitest -m GET -r /nodes/__GETNODEATTR($$CN,hcp)__
check:rc==200
cmdcheck:restapitest -o '{"__GETNODEATTR($$CN,hcp)__":"ANY"}' -O ==
end
start:node_power_get
description: node_power_get
cmd:restapitest -m GET -r /nodes/$$CN/power
check:rc==200
cmdcheck:restapitest -o '{"$$CN":{"power":"ANY"}}' -O ==
end
start:node_power_put
description: node_power_reset
cmd:restapitest -m PUT -r /nodes/$$CN/power -d '{"action":"reset"}'
check:rc==200
end
#start:node_energy_put
#description: node_energy_put
#cmd:restapitest -m PUT -r /nodes/Vc68m5sn01/energy -d '{"cappingstatus":"on"}'
#check:rc==200
#end
#start:node_energy_get
#description: node_energy_get
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/energy
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"cappingmin":"on"}}' -O ==
#end
#start:node_energy_get_attr
#description: node_energy_get_attr
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/energy/cappingmaxmin,cappingstatus
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"cappingmin":"ANY"}}' -O ==
#end
#start:node_get_attr
#description: node_get_attr
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/sp/community
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"SP SNMP Community":"public"}}' -O ==
#end
#start:node_put_attr
#description: node_put_attr
#cmd:restapitest -m PUT -r /nodes/Vc68m5sn01/sp/community -d '{"value":"mycommunity"}''
#check:rc==200
#end
#start:node_put_nextboot
#description: node_put_nextboot
#cmd:restapitest -m PUT -r /nodes/$$CN/nextboot -d '{"order":"net"}'
#check:rc==201
#end
#start:node_get_nextboot
#description: node_get_nextboot
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/nextboot
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"nextboot":"net"}}' -O ==
#end
start:node_put_bootstate
description: node_put_bootstate
cmd:restapitest -m PUT -r /nodes/Vc68m5sn01/bootstate -d '{"osimage":"rhels6.4-x86_64-install-compute"}'
check:rc==201
end
start:node_get_bootstate
description: node_get_bootstate
cmd:restapitest -m GET -r /nodes/$$CN/bootstate
check:rc==200
cmdcheck:restapitest -o '{"$$CN":{"bootstat":"ANY"}}' -O ==
end
start:node_get_vitals
description: node_get_vitals
cmd:restapitest -m GET -r /nodes/Vc68m5sn01/vitals
check:rc==200
cmdcheck:restapitest -o '{"Vc68m5sn01":{"SysBrd Fault":"0"}}' -O ==
end
start:node_get_vitals_attr
description: node_get_vitals_attr
cmd:restapitest -m GET -r /nodes/$$CN/vitals/all
check:rc==200
cmdcheck:restapitest -o '{"$$CN":{"System Temperature":"ANY"}}' -O ==
end
start:node_get_inventory
description: node_get_inventory
cmd:restapitest -m GET -r /nodes/Vc68m5sn01/inventory
check:rc==200
cmdcheck:restapitest -o '{"Vc68m5sn01":{"Power Supply 2 Board FRU Number":"94Y8105"}}' -O ==
end
start:node_get_inventory_attr
description: node_get_inventory_attr
cmd:restapitest -m GET -r /nodes/Vc68m5sn01/inventory/model
check:rc==200
cmdcheck:restapitest -o '{"Vc68m5sn01":{"System Description":"System x3650 M4"}}' -O ==
end
#start:node_get_eventlog
#description: node_get_eventlog
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/eventlog
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"eventlog":"ANY"}}' -O ==
#end
start:node_post_nodecopy
description: node_post_nodecopy
cmd:restapitest -m POST -r /nodes/$$CN/nodecopy -d '{"src":["/etc/hosts","/etc/resolv.conf"],"target":"/tmp"}'
check:rc==201
end

View File

@ -1,99 +1,82 @@
start:node_post
description: node_post
cmd:restapitest -m POST -r /nodes/node1 -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
start:create_node_rest
description: create a node with REST API
cmd:restapitest -m POST -r /nodes/restnode -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
check:rc==201
end
start:node_post2
description: node_post2
cmd:restapitest -m POST -r /nodes/node1 -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
check:rc==403
cmdcheck:restapitest -o '{"errorcode":"1"}' -O ==
start:create_node_rest2
description: create a node with REST API failure
cmd:restapitest -m POST -r /nodes/restnode -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
check:rc==147
check:output=~'errorcode' => '1'
end
start:node_put
description: node_put
cmd:restapitest -m PUT -r /nodes/node1 -d '{"mgt":"hmc","netboot":"xnba"}'
check:rc==200
end
start:nodes_get
description: nodes_get
start:get_nodes_rest
description: get all nodes with REST API
cmd:restapitest -m GET -r /nodes
check:rc==200
cmdcheck:restapitest -o '["node1"]' -O ==
check:output=~'restnode'
end
start:node_get
description: node_get
cmd:restapitest -m GET -r /nodes/node1
start:get_node_rest
description: get single node with REST API
cmd:restapitest -m GET -r /nodes/restnode
check:rc==200
cmdcheck:restapitest -o '{"node1":{"netboot":"xnba"}}' -O ==
check:output=~'restnode'
end
start:node_delete
description: node_delete
cmd:restapitest -m DELETE -r /nodes/node1
start:node_delete_rest
description: delete node with REST API
cmd:restapitest -m DELETE -r /nodes/restnode
check:rc==200
end
start:nodes_get2
description: nodes_get2
start:get_nodes_rest2
description: get all nodes with REST API
cmd:restapitest -m GET -r /nodes
check:rc==200
cmdcheck:restapitest -o '["node1"]' -O !=
check:output!~'restnode'
end
start:node_get2
description: node_get2
cmd:restapitest -m GET -r /nodes/node1
check:rc==403
cmdcheck:restapitest -o '{"errorcode":"1"}' -O ==
start:get_node_rest2
description: get single node with REST API
cmd:restapitest -m GET -r /nodes/restnode
check:rc==147
check:output=~'errorcode' => '1'
end
start:node_post3_for_get_test
description: node_post3_for_get_test
cmd:restapitest -m POST -r /nodes/node1 -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}'
start:create_node_token_rest
description: create a node with REST API using authentication token
cmd:restapitest -m POST -r /nodes/restnode -d '{"groups":"all","mgt":"dfm","netboot":"yaboot"}' -t
check:rc==201
end
start:node_attr_get
description: node_get2
cmd:restapitest -m GET -r /nodes/node1/attrs/mgt,groups,netboot
check:rc==200
cmdcheck:restapitest -o '{"node1":{"netboot":"yaboot"}}' -O ==
end
start:node_makehosts
description: node_makehosts
cmd:restapitest -m POST -r /nodes/node1/host
start:node_makehosts_rest
description: makehosts for node with REST API
cmd:restapitest -m POST -r /nodes/restnode/host
check:rc==201
end
start:node_makedns
description: node_makehosts
cmd:restapitest -m POST -r /nodes/node1/dns
start:node_makedns_rest
description: makehosts for node with REST API
cmd:restapitest -m POST -r /nodes/restnode/dns
check:rc==201
end
start:node_delete_dns
description: node_delete_dns
cmd:restapitest -m DELETE -r /nodes/node1/dns
start:node_delete_dns_rest
description: delete dns for node with REST API
cmd:restapitest -m DELETE -r /nodes/restnode/dns
check:rc==200
end
start:node_put
description: node_put
cmd:restapitest -m PUT -r /nodes/node1 -d '{"mac":"00:1a:64:54:14:80"}'
start:node_change_attr_rest
description: change node attribute with REST API
cmd:restapitest -m PUT -r /nodes/restnode -d '{"mac":"00:1a:64:54:14:80"}'
check:rc==200
end
start:node_makedhcp
description: node_makedhcp
start:node_makedhcp_rest
description: makedhcp for node with REST API
cmd:restapitest -m POST -r /nodes/node1/dhcp
check:rc==201
end
@ -104,139 +87,18 @@ cmd:restapitest -m DELETE -r /nodes/node1/dhcp
check:rc==200
end
start:node_state
description: node_state
cmd:restapitest -m GET -r /nodes/node1/nodestat
start:node_state_rest
description: get node state with REST API
cmd:restapitest -m GET -r /nodes/restnode/nodestat
check:rc==200
cmdcheck:restapitest -o '{"node1":{"nodestat":"ANY"}}' -O ==
check:output=~'restnode'
check:output=~'nodestat'
end
#start:node_post4_for_scan_test
#description: node_post4_for_scan_test
#cmd:restapitest -m POST -r /nodes/e108m6hmc02 -d '{"groups":"all,hmc","mgt":"hmc","hwtype":"hmc","mtm":"7042CR4","serial":"1050FBB","nodetype":"ppc"}'
#check:rc==201
#end
start:node_scan
description: node_scan
cmd:restapitest -m GET -r /nodes/__GETNODEATTR($$CN,hcp)__
start:node_state_token_rest
description: get node state with REST API using authentication token
cmd:restapitest -m GET -r /nodes/restnode/nodestat -t
check:rc==200
cmdcheck:restapitest -o '{"__GETNODEATTR($$CN,hcp)__":"ANY"}' -O ==
check:output=~'restnode'
check:output=~'nodestat'
end
start:node_power_get
description: node_power_get
cmd:restapitest -m GET -r /nodes/$$CN/power
check:rc==200
cmdcheck:restapitest -o '{"$$CN":{"power":"ANY"}}' -O ==
end
start:node_power_put
description: node_power_reset
cmd:restapitest -m PUT -r /nodes/$$CN/power -d '{"action":"reset"}'
check:rc==200
end
#start:node_energy_put
#description: node_energy_put
#cmd:restapitest -m PUT -r /nodes/Vc68m5sn01/energy -d '{"cappingstatus":"on"}'
#check:rc==200
#end
#start:node_energy_get
#description: node_energy_get
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/energy
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"cappingmin":"on"}}' -O ==
#end
#start:node_energy_get_attr
#description: node_energy_get_attr
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/energy/cappingmaxmin,cappingstatus
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"cappingmin":"ANY"}}' -O ==
#end
#start:node_get_attr
#description: node_get_attr
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/sp/community
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"SP SNMP Community":"public"}}' -O ==
#end
#start:node_put_attr
#description: node_put_attr
#cmd:restapitest -m PUT -r /nodes/Vc68m5sn01/sp/community -d '{"value":"mycommunity"}''
#check:rc==200
#end
#start:node_put_nextboot
#description: node_put_nextboot
#cmd:restapitest -m PUT -r /nodes/$$CN/nextboot -d '{"order":"net"}'
#check:rc==201
#end
#start:node_get_nextboot
#description: node_get_nextboot
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/nextboot
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"nextboot":"net"}}' -O ==
#end
start:node_put_bootstate
description: node_put_bootstate
cmd:restapitest -m PUT -r /nodes/Vc68m5sn01/bootstate -d '{"osimage":"rhels6.4-x86_64-install-compute"}'
check:rc==201
end
start:node_get_bootstate
description: node_get_bootstate
cmd:restapitest -m GET -r /nodes/$$CN/bootstate
check:rc==200
cmdcheck:restapitest -o '{"$$CN":{"bootstat":"ANY"}}' -O ==
end
start:node_get_vitals
description: node_get_vitals
cmd:restapitest -m GET -r /nodes/Vc68m5sn01/vitals
check:rc==200
cmdcheck:restapitest -o '{"Vc68m5sn01":{"SysBrd Fault":"0"}}' -O ==
end
start:node_get_vitals_attr
description: node_get_vitals_attr
cmd:restapitest -m GET -r /nodes/$$CN/vitals/all
check:rc==200
cmdcheck:restapitest -o '{"$$CN":{"System Temperature":"ANY"}}' -O ==
end
start:node_get_inventory
description: node_get_inventory
cmd:restapitest -m GET -r /nodes/Vc68m5sn01/inventory
check:rc==200
cmdcheck:restapitest -o '{"Vc68m5sn01":{"Power Supply 2 Board FRU Number":"94Y8105"}}' -O ==
end
start:node_get_inventory_attr
description: node_get_inventory_attr
cmd:restapitest -m GET -r /nodes/Vc68m5sn01/inventory/model
check:rc==200
cmdcheck:restapitest -o '{"Vc68m5sn01":{"System Description":"System x3650 M4"}}' -O ==
end
#start:node_get_eventlog
#description: node_get_eventlog
#cmd:restapitest -m GET -r /nodes/Vc68m5sn01/eventlog
#check:rc==200
#cmdcheck:restapitest -o '{"Vc68m5sn01":{"eventlog":"ANY"}}' -O ==
#end
start:node_post_nodecopy
description: node_post_nodecopy
cmd:restapitest -m POST -r /nodes/$$CN/nodecopy -d '{"src":["/etc/hosts","/etc/resolv.conf"],"target":"/tmp"}'
check:rc==201
end

View File

@ -151,6 +151,7 @@ The xCAT-test testing framework provides some inline functions. The inline funct
For example, to run rscan command against the hardware control point of compute node specified in the configuration file:
rscan __GETNODEATTR($$CN, hcp)__ -z
3. B<GETTABLEVALUE(keyname, key, colname, table)> To get the value of column where keyname == key in specified table.
=head1 FILES

View File

@ -4,14 +4,14 @@
# Flags are used for test input:
# -m method. Should be GET, POST, PUT, DELETE
# -r resource
# -t token
# -t
# -h host
# -u user
# -p passwd
# -P port (BC)
# -d data
# -c cert
# -n hostname
# --debug
# Flags are used for check output:
# -o expected output
# -O logical operator
@ -36,6 +36,7 @@ use strict;
my $help;
my $method;
my $token;
my $usetoken;
my $resource;
my $host;
my $user;
@ -43,7 +44,6 @@ my $passwd;
my $port;
my $data;
my $cert;
my $hostname;
my $output;
my $loperator;
my $debug;
@ -54,7 +54,7 @@ my $outputfile = "/tmp/testrestapiresult";
if (
!GetOptions("h|?" => \$help,
"m=s" => \$method,
"t=s" => \$token,
"t" => \$usetoken, # use generated token instead of the user/pw
"r=s" => \$resource,
"h=s" => \$host,
"u=s" => \$user,
@ -62,7 +62,6 @@ if (
"P=s" => \$port,
"d=s" => \$data,
"c=s" => \$cert,
"n=s" => \$hostname,
"o=s" => \$output,
"O=s" => \$loperator,
"debug" => \$debug,
@ -131,52 +130,46 @@ while (<CONF>) {
}
}
# get token
my $defaultserver = $confhash{DefaultServer};
my $defaultuser = $confhash{DefaultUser1};
my $DefaultPasswd = $confhash{DefaultPasswd1};
my $gettoken = `curl -X POST -k 'https://$defaultserver/xcatws/tokens?userName=$defaultuser&password=$DefaultPasswd' -H Content-Type:application/json --data '{"userName":"$defaultuser","password":"$DefaultPasswd"}' 2>/dev/null`;
my $reshash = parse_json($gettoken);
my $token1 = $$reshash{token}{id};
# get hostname
unless ($hostname) {
$hostname = `hostname`;
chomp($hostname);
}
unless ($defaultserver) {
# get hostname or default to local host if not specified
unless ($host) {
$host = "127.0.0.1";
} else {
$host = $defaultserver;
}
# keey default test result for save
my $res = run_restapi($method, $resource, $data, "", $port, "$host", "$defaultuser", "$DefaultPasswd");
unless ($user) {
$user = $confhash{DefaultUser1};
}
unless ($passwd) {
$passwd = $confhash{DefaultPasswd1};
}
my $DefaultPasswd = $confhash{DefaultPasswd1};
if ($usetoken) {
# get token
my $gettoken = `curl -X POST -k 'https://$host/xcatws/tokens' -H Content-Type:application/json --data '{"userName":"$user","userPW":"$passwd"}' 2>/dev/null`;
my $reshash = parse_json($gettoken);
$token = $$reshash{token}{id};
}
# debug and log info
log_debug(3, "User $user. \n");
log_debug(3, "Password $passwd. \n");
log_debug(3, "Host $host. \n");
log_debug(3, "Got token $token. \n");
log_debug(3, "get path of ca $confhash{Cert} \n");
my $res = run_restapi($method, $resource, $data, "", $port, "$host", "$user", "$passwd", "$token");
$defaulthash = parse_json($res);
$defaulthttpresult = check_errcode();
# debug and log info
log_debug(3, "get token $token1. \n");
log_debug(3, "get first default user $confhash{DefaultUser1} \n");
log_debug(3, "get first default user's passwd is $confhash{DefaultPasswd1} \n");
log_debug(3, "get second default user $confhash{DefaultUser2} \n");
log_debug(3, "get second default user's passwd is $confhash{DefaultPasswd2} \n");
log_debug(3, "get path of ca $confhash{Cert} \n");
log_debug(3, "get server $defaultserver from configuration file and it is $host\n");
log_debug(3, "get hostname $hostname.\n");
log_debug(3, "default result is $res. \n");
log_debug(3, "default resulthash is: \n");
log_debug(3, $defaulthash);
log_debug(3, "default errcode is $defaulthttpresult \n");
log_debug(3, "**************begin to run more restapi test, stop when post***************");
print Dumper $defaulthash;
exit $defaulthttpresult;
####################################################
# Begin to run test cases
####################################################
my @users = ($confhash{DefaultUser1}, $confhash{DefaultUser2}, $user);
my @passwds = ($confhash{DefaultPasswd1}, $confhash{DefaultPasswd2}, $passwd);
my @tokens = ("", $token1, $token);
my @tokens = ("", $token, $token);
my @certs = ("", $confhash{Cert}, $cert);
my $i = 0;
unless ($method eq "POST") { # Should not post sevral times
@ -235,7 +228,7 @@ sub usage
print " testrestapi [-?|-h]\n";
print " testrestapi [-m method] [-r resource] [-t tocken]\n";
print " [-h host] [-P port][-u user] [-p passwd]\n";
print " [-d data] [-c cert] [-n hostname]\n";
print " [-d data] [-c cert] \n";
print " [-o expect_output] [-O logical_operator] \n";
print " [--debug]\n";
print "\n";
@ -287,18 +280,14 @@ sub run_restapi
if ($t) {
$cmd .= " -H X-Auth-Token:$t ";
}
if ($t or $c) {
$cmd .= " 'https://$hostname";
} else {
$cmd .= " 'https://$h";
}
$cmd .= " 'https://$h";
if ($p) {
$cmd .= ":$p";
}
$cmd .= "/xcatws";
$cmd .= "$r?";
unless ($t) {
$cmd .= "userName=$u&password=$a'";
$cmd .= "userName=$u&userPW=$a'";
} else {
$cmd .= "'";
}
@ -331,7 +320,7 @@ sub parse_json
# {"networks":[{"mgtifname":"eth1","mask":"255.255.255.0"},{"mgtifname":"eth1","mask":"255.255.255.0"}]}
if ($input =~ /^\[(.*)\]$/s) {
my $content = $1;
log_debug(2, "[:] content is $content \n");
# log_debug(2, "[:] content is $content \n");
parse_json($content);
}
@ -344,7 +333,7 @@ sub parse_json
# record result
foreach my $t (@contents) {
log_debug(2, ":{}, content is $t \n");
#log_debug(2, ":{}, content is $t \n");
my $re = parse_json($t);
push @reval, $re;
}
@ -366,7 +355,7 @@ sub parse_json
# record result
foreach my $t (@contents) {
log_debug(2, "{},{}, content is $t \n");
#log_debug(2, "{},{}, content is $t \n");
my $re = parse_json($t);
push @reval, $re;
}
@ -386,7 +375,7 @@ sub parse_json
# {"clustersite":{"domain":"cluster.com","master":"192.168.1.15"}}
elsif ($input =~ /^\s*{(.*)}\s*$/s) {
my $content = $1;
log_debug(2, "{} content is $content \n");
#log_debug(2, "{} content is $content \n");
parse_json($content);
}
elsif ($input =~ /],\"\S+\":/) {
@ -396,7 +385,7 @@ sub parse_json
# record result
foreach my $t (@contents) {
log_debug(2, "],:, content is $t \n");
#log_debug(2, "],:, content is $t \n");
my $re = parse_json($t);
push @reval, $re;
}
@ -420,7 +409,7 @@ sub parse_json
# record result
foreach my $t (@contents) {
log_debug(2, ", content is $t \n");
#log_debug(2, ", content is $t \n");
my $re = parse_json($t);
push @reval, $re;
}
@ -446,7 +435,7 @@ sub parse_json
if ($value =~ /{/) {
# "clustersite":{"domain":"cluster.com","master":"192.168.1.15"}
log_debug(2, "{ content is $value \n");
#log_debug(2, "{ content is $value \n");
$hash{$key} = parse_json($value, $key);
return \%hash;
} else {
@ -464,7 +453,7 @@ sub parse_json
else {
if ($input =~ /^\[(.*)\]/s) {
my $content = $1;
log_debug(2, "[] content is $content \n");
#log_debug(2, "[] content is $content \n");
my @all = split /,/, $content;
foreach my $n (@all) {
$n =~ /\"(.*)\"/;