Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 121 additions & 19 deletions src/controller_cli_callbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -2005,10 +2005,87 @@ show_transaction_one(cxobj *xc)
return retval;
}

/*! Show one transaction in detail, human-readable (used to be a raw XML dump)
*
* @param[in] xc XML transaction
* @retval 0 OK
* @retval -1 Error
*/
static int
show_transaction_detail_one(cxobj *xc)
{
int retval = -1;
cxobj *xdevices;
cxobj *xd;
char *tid;
char *username;
char *state;
char *result;
char *reason;
char *warning;
char *description;
char *origin;
char *timestamp0;
char *timestamp;
char *dname;
char *dresult;
char *dreason;
struct timeval tv0;
struct timeval tv1;
struct timeval tvdiff;

tid = xml_find_body(xc, "tid");
username = xml_find_body(xc, "username");
state = xml_find_body(xc, "state");
result = xml_find_body(xc, "result");
reason = xml_find_body(xc, "reason");
warning = xml_find_body(xc, "warning");
description = xml_find_body(xc, "description");
origin = xml_find_body(xc, "origin");
timestamp0 = xml_find_body(xc, "timestamp0");
timestamp = xml_find_body(xc, "timestamp");

cligen_output(stdout, "Transaction %s\n", tid?tid:"-");
cligen_output(stdout, " %-13s%s\n", "User:", username?username:"-");
cligen_output(stdout, " %-13s%s\n", "State:", state?state:"-");
cligen_output(stdout, " %-13s%s\n", "Result:", result?result:"-");
cligen_output(stdout, " %-13s%s\n", "Description:", description?description:"-");
if (origin)
cligen_output(stdout, " %-13s%s\n", "Origin:", origin);
cligen_output(stdout, " %-13s%s\n", "Started:", timestamp0?timestamp0:"-");
cligen_output(stdout, " %-13s%s\n", "Ended:", timestamp?timestamp:"-");
if (timestamp0 && timestamp &&
str2time(timestamp0, &tv0) == 0 && str2time(timestamp, &tv1) == 0){
timersub(&tv1, &tv0, &tvdiff);
cligen_output(stdout, " %-13s%ld.%03lds\n", "Duration:",
tvdiff.tv_sec, tvdiff.tv_usec/1000);
}
if (reason)
cligen_output(stdout, " %-13s%s\n", "Reason:", reason);
else if (warning)
cligen_output(stdout, " %-13s%s\n", "Warning:", warning);
if ((xdevices = xml_find_type(xc, NULL, "devices", CX_ELMNT)) != NULL){
cligen_output(stdout, " Devices:\n");
xd = NULL;
while ((xd = xml_child_each(xdevices, xd, CX_ELMNT)) != NULL){
if (strcmp(xml_name(xd), "device") != 0)
continue;
dname = xml_find_body(xd, "name");
dresult = xml_find_body(xd, "result");
dreason = xml_find_body(xd, "reason");
cligen_output(stdout, " %-12s%-10s%s\n",
dname?dname:"-", dresult?dresult:"-", dreason?dreason:"");
}
}
cligen_output(stdout, "\n");
retval = 0;
return retval;
}

/*! Show controller device states
*
* @param[in] h
* @param[in] cvv Keywords could be "detail", "all"
* @param[in] cvv Keywords could be "detail", "all", "tid"
* @param[in] argv
* @retval 0 OK
* @retval -1 Error
Expand All @@ -2018,47 +2095,70 @@ cli_show_transactions(clixon_handle h,
cvec *cvv,
cvec *argv)
{
int retval = -1;
cvec *nsc = NULL;
cxobj *xc;
cxobj *xt;
cxobj *xerr;
cxobj *xn = NULL; /* XML of transactions */
int all;
int detail;
int nr;
int i;
int retval = -1;
cvec *nsc = NULL;
cxobj *xc;
cxobj *xt;
cxobj *xerr;
cxobj *xn = NULL; /* XML of transactions */
cbuf *cbxp = NULL;
cg_var *cvtid;
uint64_t tid = 0;
int all;
int detail;
int nr;
int i;

all = cvec_find(cvv, "all") != NULL;
detail = cvec_find(cvv, "detail") != NULL;
if ((cvtid = cvec_find(cvv, "tid")) != NULL){
tid = cv_uint64_get(cvtid);
detail = 1; /* A single explicitly named transaction is always shown in detail */
}
/* Get config */
if ((nsc = xml_nsctx_init("co", CONTROLLER_NAMESPACE)) == NULL)
goto done;
if (clicon_rpc_get(h, "co:transactions", nsc, CONTENT_ALL, -1, "report-all", &xn) < 0)
if ((cbxp = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
if (tid)
cprintf(cbxp, "co:transactions/co:transaction[co:tid='%" PRIu64 "']", tid);
else
cprintf(cbxp, "co:transactions");
if (clicon_rpc_get(h, cbuf_get(cbxp), nsc, CONTENT_ALL, -1, "report-all", &xn) < 0)
goto done;
if ((xerr = xpath_first(xn, NULL, "/rpc-error")) != NULL){
clixon_err_netconf(h, OE_XML, 0, xerr, "Get transactions");
goto done;
}
/* Change top from "data" to "transactions" */
if ((xc = xml_find_type(xn, NULL, "transactions", CX_ELMNT)) != NULL){
if ((xc = xml_find_type(xn, NULL, "transactions", CX_ELMNT)) == NULL){
if (tid)
cligen_output(stderr, "No such transaction: %" PRIu64 "\n", tid);
}
else{
if (xml_rootchild_node(xn, xc) < 0)
goto done;
xn = xc;
nr = xml_child_nr_type(xn, CX_ELMNT);
if (tid && nr == 0){
cligen_output(stderr, "No such transaction: %" PRIu64 "\n", tid);
goto ok;
}
if (detail){
/* Detail mode: show full XML */
if (all){
nr = xml_child_nr_type(xn, CX_ELMNT);
/* Detail mode: human-readable per-transaction breakdown */
if (all || tid){
for (i = nr; i > 0; i--){
if ((xc = xml_child_i(xn, i)) != NULL){
if (clixon_xml2file(stdout, xc, 0, 1, NULL, cligen_output, 0, 1) < 0)
if (show_transaction_detail_one(xc) < 0)
goto done;
}
}
}
else{
if ((xc = xml_child_i(xn, xml_child_nr(xn) - 1)) != NULL){
if (clixon_xml2file(stdout, xc, 0, 1, NULL, cligen_output, 0, 1) < 0)
if (show_transaction_detail_one(xc) < 0)
goto done;
}
}
Expand All @@ -2074,7 +2174,6 @@ cli_show_transactions(clixon_handle h,
"--------",
"------------------------------");
if (all){
nr = xml_child_nr_type(xn, CX_ELMNT);
for (i = nr; i > 0; i--){
if ((xc = xml_child_i(xn, i)) != NULL){
if (show_transaction_one(xc) < 0)
Expand All @@ -2090,8 +2189,11 @@ cli_show_transactions(clixon_handle h,
}
}
}
ok:
retval = 0;
done:
if (cbxp)
cbuf_free(cbxp);
if (nsc)
cvec_free(nsc);
if (xn)
Expand Down
4 changes: 3 additions & 1 deletion src/controller_operation.cli
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ show("Show a particular state of the system"){
@|pipe_common, cli_show_statistics();
}
transactions("Show state of last transaction"){
[<all:string keyword:all>] [<detail:string keyword:detail>], cli_show_transactions();
[(<all:string keyword:all>("Show all transactions")|
<tid:uint64>("Show a specific transaction by id"))]
[<detail:string keyword:detail>], cli_show_transactions();
@|pipe_show, cli_show_transactions();
}
version("Show version"), cli_controller_show_version();
Expand Down
16 changes: 14 additions & 2 deletions src/controller_rpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3806,6 +3806,7 @@ rpc_device_rpc_template_apply(clixon_handle h,
cvec *nsc = NULL;
controller_transaction *ct = NULL;
cbuf *cberr = NULL;
cbuf *cbtr = NULL;
int groups = 0;
cvec *devvec = NULL;
cg_var *cv;
Expand Down Expand Up @@ -3892,8 +3893,17 @@ rpc_device_rpc_template_apply(clixon_handle h,
if (xml_sort_recurse(xconfig) < 0)
goto done;
}
/* Initiate new transaction */
if ((ret = controller_transaction_new(h, ce, clicon_username_get(h), "rpc-device template", 0, &ct, &cberr)) < 0)
/* Initiate new transaction
* Include the template name in the description so it shows up in
* "show transactions" / "show transactions detail" instead of just
* the generic "rpc-device template".
*/
if ((cbtr = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
cprintf(cbtr, "rpc-device template %s", tmplname ? tmplname : "(inline)");
if ((ret = controller_transaction_new(h, ce, clicon_username_get(h), cbuf_get(cbtr), 0, &ct, &cberr)) < 0)
goto done;
if (ret == 0){
if (netconf_operation_failed(cbret, "application", "%s", cbuf_get(cberr))< 0)
Expand Down Expand Up @@ -3936,6 +3946,8 @@ rpc_device_rpc_template_apply(clixon_handle h,
done:
if (cberr)
cbuf_free(cberr);
if (cbtr)
cbuf_free(cbtr);
if (cvv)
cvec_free(cvv);
if (xret)
Expand Down
6 changes: 3 additions & 3 deletions test/test-c-service.sh
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ fi
new "commit diff 4: devices in transaction"
ret=$(${clixon_cli} -1f $CFG -E $CFD show transactions detail 2>&1)
#echo "ret:$ret"
match=$(echo "$ret" | grep --null -Eo "<name>${IMG}1</name>") || true
match=$(echo "$ret" | grep --null -E "^ ${IMG}1[[:space:]]") || true
if [ -z "$match" ]; then
err "${IMG}1 in transaction detail" "$ret"
fi
Expand Down Expand Up @@ -862,8 +862,8 @@ function check_devresult()
local devblock

out=$(${clixon_cli} -1f $CFG -E $CFD show transactions detail 2>&1)
devblock=$(echo "$out" | grep -A 5 "<name>$dev</name>")
resblock=$(echo "$out" | grep "<result>$res</result>")
devblock=$(echo "$out" | grep -E "^ ${dev}[[:space:]]")
resblock=$(echo "$out" | grep -E "^ Result:[[:space:]]*${res}$")
if [ -z "$resblock" ]; then
err1 "result=$res in transaction detail" "$out"
fi
Expand Down
4 changes: 2 additions & 2 deletions test/test-commit-lock-fail.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,13 @@ expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transactions)" 0 "FAILED"

new "show transactions detail: $DEV1 result FAILED (own lock failure)"
out=$($clixon_cli -1 -f $CFG -E $CFD show transactions detail 2>&1)
devblock=$(echo "$out" | grep -A 5 "<name>$DEV1</name>")
devblock=$(echo "$out" | grep -E "^ ${DEV1}[[:space:]]")
if ! echo "$devblock" | grep -q "FAILED"; then
err1 "$DEV1 result FAILED in transaction detail" "$out"
fi

new "show transactions detail: $DEV2 result FAILED (aborted due to peer failure, not left as default SUCCESS)"
devblock=$(echo "$out" | grep -A 5 "<name>$DEV2</name>")
devblock=$(echo "$out" | grep -E "^ ${DEV2}[[:space:]]")
if ! echo "$devblock" | grep -q "FAILED"; then
err1 "$DEV2 result FAILED in transaction detail" "$out"
fi
Expand Down
2 changes: 1 addition & 1 deletion test/test-connect-timeout-error.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ new "wait past connect-timeout"
sleep 6

new "show transactions detail: $DEV marked ERROR after connect-timeout"
expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transactions detail)" 0 "<name>$DEV</name>" "<result>ERROR</result>" "Timeout waiting for remote peer"
expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transactions detail)" 0 "$DEV.*ERROR" "Timeout waiting for remote peer"

new "show transactions: brief table Devices column shows 1 ERROR"
expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transactions)" 0 "1 ERROR"
Expand Down
2 changes: 1 addition & 1 deletion test/test-connect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ if [ "$res" != "$nr1" ]; then
fi

new "Check errmsg"
expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transaction detail)" 0 "<result>FAILED</result>" "<reason>wrong@" "Permission denied (publickey,password,keyboard-interactive).</reason>" || true
expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transactions detail)" 0 "Result:.*FAILED" "wrong@" "Permission denied (publickey,password,keyboard-interactive)."

new "Verify first device is framing 1.0"
expectpart "$($clixon_cli -1 -f $CFG -E $CFD show state devices device ${IMG}1 netconf-framing)" 0 "netconf-framing 1.0"
Expand Down
2 changes: 1 addition & 1 deletion test/test-dead-connection-fast-fail.sh
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ expectpart "$($clixon_cli -1 -f $CFG -E $CFD show transactions)" 0 "FAILED"

new "show transactions detail: $DEV marked FAILED"
out=$($clixon_cli -1 -f $CFG -E $CFD show transactions detail 2>&1)
devblock=$(echo "$out" | grep -A 5 "<name>$DEV</name>")
devblock=$(echo "$out" | grep -E "^ ${DEV}[[:space:]]")
if [ -z "$devblock" ]; then err1 "$DEV in transaction detail" "$out"; fi
if ! echo "$devblock" | grep -q "FAILED"; then
err1 "$DEV result FAILED in transaction detail" "$out"
Expand Down
6 changes: 3 additions & 3 deletions test/test-service-lock.sh
Original file line number Diff line number Diff line change
Expand Up @@ -265,10 +265,10 @@ new "Wait until timeout"
sleep 10

new "Verify action timeout"
ret=$($clixon_cli -1 -f $CFG -E $CFD show transaction detail)
match=$(echo "$ret" | grep --null -Eo "<reason>Timeout waiting for service daemon</reason>") || true
ret=$($clixon_cli -1 -f $CFG -E $CFD show transactions detail)
match=$(echo "$ret" | grep --null -F "Timeout waiting for service daemon") || true
if [ -z "$match" ]; then
err "<Timeout>" "$ret"
err "Timeout waiting for service daemon" "$ret"
fi

new "restconf POST service CC" # Here is still held
Expand Down
Loading
Loading