Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

redfishpower: add option to test host errors #145

Merged
merged 10 commits into from
Feb 22, 2024
12 changes: 6 additions & 6 deletions man/redfishpower.8.in
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ set simultaneously is limited by the file descriptor limit of the
system call.
.TP
.I "-H, --header string"
Set extra HEADER to use.
Set extra HEADER to use. Typically is Content-Type:application/json.
.TP
.I "-S, --statpath string"
Set Redfish path for obtaining power status. Typically is redfish/v1/Systems/1.
Expand Down Expand Up @@ -60,14 +60,14 @@ Set extra HEADER to use. Do not specify data to clear.
.I "setstatpath <path>"
Set path to obtain power status.
.TP
.I "setonpath <path> [data]"
.I "setonpath <path> [postdata]"
Set path and optional post data to turn on node.
.TP
.I "setoffpath <path> [data]"
.I "setoffpath <path> [postdata]"
Set path and optional post data to turn off node.
.TP
.I "setcyclepath <path> [data]"
Set path and optional post data to turn cycle node.
.I "setcyclepath <path> [postdata]"
Set path and optional post data to cycle node.
.TP
.I "settimeout <seconds>"
Set command timeout in seconds.
Expand All @@ -82,7 +82,7 @@ Turn on all nodes or specified subset of nodes. Will return "ok" after confirma
Turn off all nodes or specified subset of nodes. Will return "ok" after confirmation "off" has completed.
.TP
.I "cycle [nodes]"
Turn off all nodes or specified subset of nodes.
Power cycle all nodes or specified subset of nodes.

.SH "UPDATING REDFISHPOWER DEVICE FILES"
.LP
Expand Down
138 changes: 80 additions & 58 deletions src/redfishpower/redfishpower.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ static char *cyclepath = NULL;
static char *cyclepostdata = NULL;

static int test_mode = 0;
static zhashx_t *test_power_status = NULL;
static hostlist_t test_fail_power_cmd_hosts;
static zhashx_t *test_power_status;

/* in seconds */
#define MESSAGE_TIMEOUT 10
Expand Down Expand Up @@ -113,7 +114,7 @@ struct powermsg {
err_exit(false, "curl_easy_setopt: %s", curl_easy_strerror(_ec)); \
} while(0)

#define OPTIONS "h:H:S:O:F:C:P:G:D:Tv"
#define OPTIONS "h:H:S:O:F:C:P:G:D:TEv"
static struct option longopts[] = {
{"hostname", required_argument, 0, 'h' },
{"header", required_argument, 0, 'H' },
Expand All @@ -125,6 +126,7 @@ static struct option longopts[] = {
{"offpostdata", required_argument, 0, 'G' },
{"cyclepostdata", required_argument, 0, 'D' },
{"test-mode", no_argument, 0, 'T' },
{"test-fail-power-cmd-hosts", required_argument, 0, 'E' },
{"verbose", no_argument, 0, 'v' },
{0,0,0,0},
};
Expand All @@ -136,10 +138,10 @@ void help(void)
printf("Valid commands are:\n");
printf(" auth user:passwd\n");
printf(" setheader string\n");
printf(" setstatpath url\n");
printf(" setonpath url [data]\n");
printf(" setoffpath url [data]\n");
printf(" setcyclepath url [data]\n");
printf(" setstatpath path\n");
printf(" setonpath path [postdata]\n");
printf(" setoffpath path [postdata]\n");
printf(" setcyclepath path [postdata]\n");
printf(" settimeout seconds\n");
printf(" stat [nodes]\n");
printf(" on [nodes]\n");
Expand All @@ -149,26 +151,26 @@ void help(void)

static size_t output_cb(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct powermsg *pm = userp;

if (pm->output) {
char *tmp = calloc(1, pm->output_len + realsize + 1);
if (!tmp)
err_exit(true, "calloc");
memcpy(tmp, pm->output, pm->output_len);
memcpy(tmp + pm->output_len, contents, realsize);
pm->output_len += realsize;
free(pm->output);
pm->output = tmp;
}
else {
if (!(pm->output = calloc(1, realsize + 1)))
err_exit(true, "calloc");
memcpy(pm->output, contents, realsize);
pm->output_len = realsize;
}
return realsize;
size_t realsize = size * nmemb;
struct powermsg *pm = userp;

if (pm->output) {
char *tmp = calloc(1, pm->output_len + realsize + 1);
if (!tmp)
err_exit(true, "calloc");
memcpy(tmp, pm->output, pm->output_len);
memcpy(tmp + pm->output_len, contents, realsize);
pm->output_len += realsize;
free(pm->output);
pm->output = tmp;
}
else {
if (!(pm->output = calloc(1, realsize + 1)))
err_exit(true, "calloc");
memcpy(pm->output, contents, realsize);
pm->output_len = realsize;
}
return realsize;
}

static struct powermsg *powermsg_create(CURLM *mh,
Expand Down Expand Up @@ -329,9 +331,9 @@ static struct powermsg *stat_cmd_host(CURLM * mh, char *hostname)

static void stat_cmd(zlistx_t *activecmds, CURLM *mh, char **av)
{
hostlist_iterator_t itr = NULL;
hostlist_iterator_t itr;
char *hostname;
hostlist_t *hostsptr = NULL;
hostlist_t *hostsptr;
hostlist_t lhosts = NULL;

if (!statpath) {
Expand Down Expand Up @@ -410,7 +412,7 @@ static void parse_onoff(struct powermsg *pm, const char **strp)
}
}

static void stat_process (struct powermsg *pm)
static void stat_process(struct powermsg *pm)
{
const char *str;
parse_onoff(pm, &str);
Expand Down Expand Up @@ -452,9 +454,9 @@ static void power_cmd(zlistx_t *activecmds,
const char *path,
const char *postdata)
{
hostlist_iterator_t itr = NULL;
hostlist_iterator_t itr;
char *hostname;
hostlist_t *hostsptr = NULL;
hostlist_t *hostsptr;
hostlist_t lhosts = NULL;

if (!path) {
Expand Down Expand Up @@ -675,26 +677,27 @@ static void setpowerpath(char **av, char **path, char **postdata)
xfree(*postdata);
*postdata = NULL;
}
if (av[0])
if (av[0]) {
(*path) = xstrdup(av[0]);
if (av[1])
(*postdata) = xstrdup(av[1]);
if (av[1])
(*postdata) = xstrdup(av[1]);
}
Comment on lines -678 to +684
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated but the parens on the LHS are unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya know, I always paren these de-reference assignments ... I don't know why. Somehow makes it more clear to me that's an assignment? Or maybe I picked it up via another project.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, if they are helping!

}

static void settimeout(char **av)
{
if (av[0]) {
char *endptr;
long tmp;

errno = 0;
tmp = strtol (av[0], &endptr, 10);
if (errno
|| endptr[0] != '\0'
|| tmp <= 0)
printf("invalid timeout specified\n");
cmd_timeout = tmp;
}
if (av[0]) {
char *endptr;
long tmp;

errno = 0;
tmp = strtol (av[0], &endptr, 10);
if (errno
|| endptr[0] != '\0'
|| tmp <= 0)
printf("invalid timeout specified\n");
cmd_timeout = tmp;
}
}

static void process_cmd(zlistx_t *activecmds, CURLM *mh, char **av, int *exitflag)
Expand Down Expand Up @@ -758,6 +761,7 @@ static void shell(CURLM *mh)

if (!(delayedcmds = zlistx_new()))
err_exit(true, "zlistx_new");
zlistx_set_destructor(delayedcmds, cleanup_powermsg);

while (exitflag == 0) {
CURLMcode mc;
Expand Down Expand Up @@ -956,7 +960,10 @@ static void shell(CURLM *mh)
/* in test mode we assume all activecmds complete immediately */
struct powermsg *pm = zlistx_first(activecmds);
while (pm) {
power_cmd_process(delayedcmds, pm);
if (hostlist_find(test_fail_power_cmd_hosts, pm->hostname) >= 0)
printf("%s: %s\n", pm->hostname, "error");
else
power_cmd_process(delayedcmds, pm);
fflush(stdout);
zlistx_detach_cur(activecmds);
pm = zlistx_next(activecmds);
Expand Down Expand Up @@ -992,10 +999,30 @@ static void init_redfishpower(char *argv[])
if (!(hosts = hostlist_create(NULL)))
err_exit(true, "hostlist_create error");

if (!(test_fail_power_cmd_hosts = hostlist_create(NULL)))
err_exit(true, "hostlist_create error");

if (!(test_power_status = zhashx_new ()))
err_exit(false, "zhashx_new error");
}

static void cleanup_redfishpower(void)
{
xfree(userpwd);
xfree(statpath);
xfree(onpath);
xfree(onpostdata);
xfree(offpath);
xfree(offpostdata);
xfree(cyclepath);
xfree(cyclepostdata);

hostlist_destroy(hosts);

hostlist_destroy(test_fail_power_cmd_hosts);
zhashx_destroy(&test_power_status);
}

int main(int argc, char *argv[])
{
CURLM *mh = NULL;
Expand Down Expand Up @@ -1037,6 +1064,10 @@ int main(int argc, char *argv[])
case 'T': /* --test-mode */
test_mode = 1;
break;
case 'E': /* --test-fail-power-cmd-hosts */
if (!hostlist_push(test_fail_power_cmd_hosts, optarg))
err_exit(true, "hostlist_push error on %s", optarg);
break;
case 'v': /* --verbose */
verbose = 1;
break;
Expand All @@ -1060,7 +1091,7 @@ int main(int argc, char *argv[])
}
else {
/* All hosts initially are off for testing */
hostlist_iterator_t itr = NULL;
hostlist_iterator_t itr;
char *hostname;
if (!(itr = hostlist_iterator_create(hosts)))
err_exit(true, "hostlist_iterator_create");
Expand All @@ -1077,16 +1108,7 @@ int main(int argc, char *argv[])
if (!test_mode)
curl_multi_cleanup(mh);

xfree(userpwd);
hostlist_destroy(hosts);
xfree(statpath);
xfree(onpath);
xfree(onpostdata);
xfree(offpath);
xfree(offpostdata);
xfree(cyclepath);
xfree(cyclepostdata);
zhashx_destroy(&test_power_status);
cleanup_redfishpower();
exit(0);
}

Expand Down
42 changes: 42 additions & 0 deletions t/t0029-redfish.t
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ makeoutput() {
printf "unknown: %s\n" $3
}

#
# redfishpower core tests
#

test_expect_success 'create powerman.conf for 16 cray redfish nodes' '
cat >powerman.conf <<-EOT
listen "$testaddr"
Expand Down Expand Up @@ -102,6 +106,44 @@ test_expect_success 'stop powerman daemon' '
kill -15 $(cat powermand.pid) &&
wait
'

#
# redfishpower fail hosts coverage
#

test_expect_success 'create powerman.conf for 16 cray redfish nodes (failhosts)' '
cat >powerman_fail_hosts.conf <<-EOT
listen "$testaddr"
include "$devicesdir/redfishpower-cray-r272z30.dev"
device "d0" "redfishpower-cray-r272z30" "$redfishdir/redfishpower -h t[0-15] --test-mode --test-fail-power-cmd-hosts=t[8-15] |&"
node "t[0-15]" "d0"
EOT
'
test_expect_success 'start powerman daemon and wait for it to start (failhosts)' '
$powermand -Y -c powerman_fail_hosts.conf &
echo $! >powermand.pid &&
$powerman --retry-connect=100 --server-host=$testaddr -d
'
test_expect_success 'powerman -q shows t[0-7] off, t[8-15] unknown' '
$powerman -h $testaddr -q >test_failhosts_query.out &&
makeoutput "" "t[0-7]" "t[8-15]" >test_failhosts_query.exp &&
test_cmp test_failhosts_query.exp test_failhosts_query.out
'
test_expect_success 'powerman -1 t[0-15] completes' '
$powerman -h $testaddr -1 t[0-15] >test_failhosts_on.out &&
echo Command completed successfully >test_failhosts_on.exp &&
test_cmp test_failhosts_on.exp test_failhosts_on.out
'
test_expect_success 'powerman -q shows t[0-7] on' '
$powerman -h $testaddr -q >test_failhosts_query2.out &&
makeoutput "t[0-7]" "" "t[8-15]" >test_failhosts_query2.exp &&
test_cmp test_failhosts_query2.exp test_failhosts_query2.out
'
test_expect_success 'stop powerman daemon (failhosts)' '
kill -15 $(cat powermand.pid) &&
wait
'

test_done

# vi: set ft=sh
Loading