diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a083ae4..183fddfd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Expected: April Developers may need to change their code +* Removed `cli_debug()`. Use `cli_debug_backend()` or `cli_debug_restconf()` instead. * Removed `yspec_free()` - replace with `ys_free()` * Removed `endtag` parameter of `clixon_xml_parse_file()` * Restconf authentication callback (ca_auth) signature changed (again) diff --git a/apps/cli/cli_common.c b/apps/cli/cli_common.c index b2be4f3f..4825ff99 100644 --- a/apps/cli/cli_common.c +++ b/apps/cli/cli_common.c @@ -499,6 +499,10 @@ cli_debug_backend(clicon_handle h, * @param[in] arg Else use the integer value of argument * @note The level is either what is specified in arg as int argument. * _or_ if a 'level' variable is present in vars use that value instead. + * @notes + * 1. clixon-restconf.yang is used (so that debug config can be set) + * 2. AND the XML is in running db not in clixon-config (so that restconf read the new config from backend) + * 3 CLICON_BACKEND_RESTCONF_PROCESS is true (so that backend restarts restconf) */ int cli_debug_restconf(clicon_handle h, @@ -518,8 +522,7 @@ cli_debug_restconf(clicon_handle h, } level = cv_int32_get(cv); /* restconf daemon */ - if (0) /* XXX notyet */ - retval = clicon_rpc_debug(h, level); + retval = clicon_rpc_restconf_debug(h, level); done: return retval; } @@ -1302,32 +1305,6 @@ cli_copy_config(clicon_handle h, return retval; } - -/*! set debug level on stderr (not syslog). - * The level is either what is specified in arg as int argument. - * _or_ if a 'level' variable is present in vars use that value instead. - * XXX obsolete. Use cli_debug_cliv or cli_debug_backendv instead - */ -int -cli_debug(clicon_handle h, - cvec *vars, - cg_var *arg) -{ - cg_var *cv; - int level; - - if ((cv = cvec_find(vars, "level")) == NULL) - cv = arg; - level = cv_int32_get(cv); - /* cli */ - clicon_debug_init(level, NULL); /* 0: dont debug, 1:debug */ - /* config daemon */ - if (clicon_rpc_debug(h, level) < 0) - goto done; - done: - return 0; -} - int cli_help(clicon_handle h, cvec *vars, cvec *argv) { diff --git a/apps/restconf/restconf_main_evhtp.c b/apps/restconf/restconf_main_evhtp.c index a9e5db6c..0de3ab77 100644 --- a/apps/restconf/restconf_main_evhtp.c +++ b/apps/restconf/restconf_main_evhtp.c @@ -979,8 +979,14 @@ cx_evhtp_init(clicon_handle h, (bstr = xml_body(x)) != NULL){ dbg = atoi(bstr); clicon_debug_init(dbg, NULL); + /* If debug was enabled here from config and not initially, + * print clixn options and loaded yang files + */ + if (dbg) { + clicon_option_dump(h, dbg); + yang_spec_dump(clicon_dbspec_yang(h), dbg); + } } - /* Here the daemon either uses SSL or not, ie you cant seem to mix http and https :-( */ if (ssl_enable){ /* Init evhtp ssl config struct */ diff --git a/doc/DEVELOP.md b/doc/DEVELOP.md index 21867f0f..b711763b 100644 --- a/doc/DEVELOP.md +++ b/doc/DEVELOP.md @@ -68,19 +68,43 @@ How to debug CFLAGS="-g -Wall" INSTALLFLAGS="" ./configure ``` -### Set backend debug using curl +### Set backend debug -Set backend debug using rpc +Using netconf: +``` +1 +``` + +Using curl: +``` curl -Ssik -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/operations/clixon-lib:debug -d '{"clixon-lib:input":{"level":1}}' +``` -### Set restconf debug using curl +### Set restconf debug -Only if using clixon-restconf.yang +All three must be true: + 1. clixon-restconf.yang is used (so that debug config can be set) + 2. AND the XML is in running db not in clixon-config (so that restconf reads the new config from backend) + 3 CLICON_BACKEND_RESTCONF_PROCESS is true (so that backend restarts restconf) -curl -Ssik -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/clixon-rstconf:restconf/debug -d '{"clixon-restconf:debug":{"level":1}}' +Otherwise you need to restart clixon_restconf manually -Get restconf daemon status +Using netconf: +``` +clixon_netconf -q -o CLICON_NETCONF_HELLO_OPTIONAL=true <1]]>]]> +]]>]]> +EOF +``` +Using restconf/curl +``` +curl -Ssik -X PUT -H "Content-Type: application/yang-data+json" http://localhost/restconf/data/clixon-restconf:restconf/debug -d '{"clixon-restconf:debug":1}' +``` + +Get restconf daemon status: +``` curl -Ssik -X POST -H "Content-Type: application/yang-data+json" http://localhost/restconf/operations/clixon-lib:process-control -d '{"clixon-lib:input":{"name":"restconf","operation":"status"}}' +``` ### Make your own simplified yang and configuration file. ``` diff --git a/lib/clixon/clixon_proto_client.h b/lib/clixon/clixon_proto_client.h index 7b3aef07..035b0bcc 100644 --- a/lib/clixon/clixon_proto_client.h +++ b/lib/clixon/clixon_proto_client.h @@ -62,6 +62,7 @@ int clicon_rpc_commit(clicon_handle h); int clicon_rpc_discard_changes(clicon_handle h); int clicon_rpc_create_subscription(clicon_handle h, char *stream, char *filter, int *s); int clicon_rpc_debug(clicon_handle h, int level); +int clicon_rpc_restconf_debug(clicon_handle h, int level); int clicon_hello_req(clicon_handle h, uint32_t *id); #endif /* _CLIXON_PROTO_CLIENT_H_ */ diff --git a/lib/clixon/clixon_yang.h b/lib/clixon/clixon_yang.h index 956ef74e..5a882e03 100644 --- a/lib/clixon/clixon_yang.h +++ b/lib/clixon/clixon_yang.h @@ -234,6 +234,7 @@ int yang_order(yang_stmt *y); int yang_print_cb(FILE *f, yang_stmt *yn, clicon_output_cb *fn); int yang_print(FILE *f, yang_stmt *yn); int yang_print_cbuf(cbuf *cb, yang_stmt *yn, int marginal); +int yang_spec_dump(yang_stmt *yspec, int debuglevel); int if_feature(yang_stmt *yspec, char *module, char *feature); int ys_populate(yang_stmt *ys, void *arg); int ys_populate2(yang_stmt *ys, void *arg); diff --git a/lib/src/clixon_proto_client.c b/lib/src/clixon_proto_client.c index d090ed82..fb22d5dc 100644 --- a/lib/src/clixon_proto_client.c +++ b/lib/src/clixon_proto_client.c @@ -1164,6 +1164,57 @@ clicon_rpc_debug(clicon_handle h, return retval; } +/*! Send a debug request to backend server to set restconf debug + * @param[in] h CLICON handle + * @param[in] level Debug level + * @retval 0 OK + * @retval -1 Error and logged to syslog + * @note The following must hold: + * 1. clixon-restconf.yang is used (so that debug config can be set) + * 2. AND the XML is in running db not in clixon-config (so that restconf reads the new config from backend) + * 3 CLICON_BACKEND_RESTCONF_PROCESS is true (so that backend restarts restconf) + */ +int +clicon_rpc_restconf_debug(clicon_handle h, + int level) +{ + int retval = -1; + struct clicon_msg *msg = NULL; + cxobj *xret = NULL; + cxobj *xerr; + char *username; + uint32_t session_id; + + if (session_id_check(h, &session_id) < 0) + goto done; + username = clicon_username_get(h); + if ((msg = clicon_msg_encode(session_id, + "%d", + NETCONF_BASE_NAMESPACE, + username?username:"", + CLIXON_RESTCONF_NS, + level)) == NULL) + goto done; + if (clicon_rpc_msg(h, msg, &xret) < 0) + goto done; + if ((xerr = xpath_first(xret, NULL, "//rpc-error")) != NULL){ + clixon_netconf_error(xerr, "Debug", NULL); + goto done; + } + if (xpath_first(xret, NULL, "//rpc-reply/ok") == NULL){ + clicon_err(OE_XML, 0, "rpc error"); /* XXX extract info from rpc-error */ + goto done; + } + if ((retval = clicon_rpc_commit(h)) < 0) + goto done; + done: + if (msg) + free(msg); + if (xret) + xml_free(xret); + return retval; +} + /*! Send a hello request to the backend server * @param[in] h CLICON handle * @param[in] level Debug level diff --git a/lib/src/clixon_yang.c b/lib/src/clixon_yang.c index 7ff8e867..1d0ea4f6 100644 --- a/lib/src/clixon_yang.c +++ b/lib/src/clixon_yang.c @@ -1466,6 +1466,40 @@ yang_print(FILE *f, return yang_print_cb(f, yn, fprintf); } +/* Log/debug info about top-level (sub)modules no recursion + * @param[in] f File to print to. + * @param[in] yspec Yang spec + */ +int +yang_spec_dump(yang_stmt *yspec, + int dbglevel) +{ + int retval = -1; + yang_stmt *ym = NULL; + yang_stmt *yrev; + cbuf *cb = NULL; + + if ((cb = cbuf_new()) ==NULL){ + clicon_err(OE_YANG, errno, "cbuf_new"); + goto done; + } + while ((ym = yn_each(yspec, ym)) != NULL) { + cprintf(cb, "%s", yang_key2str(ym->ys_keyword)); + cprintf(cb, " %s", ym->ys_argument); + if ((yrev = yang_find(ym, Y_REVISION, NULL)) != NULL){ + cprintf(cb, "@%u", cv_uint32_get(yang_cv_get(yrev))); + } + cprintf(cb, ".yang"); + clicon_debug(dbglevel, "%s", cbuf_get(cb)); + cbuf_reset(cb); + } + retval = 0; + done: + if (cb) + cbuf_free(cb); + return retval; +} + /*! Print yang specification to cligen buf * @param[in] cb Cligen buffer. This is where the pretty print is. * @param[in] yn Yang node to print diff --git a/test/test_restconf.sh b/test/test_restconf.sh index 5f09b10e..4af53375 100755 --- a/test/test_restconf.sh +++ b/test/test_restconf.sh @@ -14,6 +14,7 @@ # (4) local/backend config. Evhtp only # - The tests runs through both (if compiled with evhtp) # See also test_restconf2.sh +# See test_restconf_rpc.sh for cases when CLICON_BACKEND_RESTCONF_PROCESS is set # Magic line must be first in script (see README.md) s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi diff --git a/test/test_restconf_rpc.sh b/test/test_restconf_rpc.sh index dc13770c..79b76c96 100755 --- a/test/test_restconf_rpc.sh +++ b/test/test_restconf_rpc.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # Restconf direct start/stop using RPC and config enable flag (as alternative to systemd or other) -# According tot he following behaviour: +# According to the following behaviour: # - on RPC start, if enable is true, start the service, if false, error or ignore it # - on RPC stop, stop the service # - on backend start make the state as configured