* Removed cli_debug(). Use cli_debug_backend() or cli_debug_restconf() instead.

* Created restconf debug rpc stub function and documented restconf debugging
This commit is contained in:
Olof hagsand 2021-03-22 14:56:05 +01:00
parent 6d23963d8b
commit 709459304f
10 changed files with 132 additions and 36 deletions

View file

@ -48,6 +48,7 @@ Expected: April
Developers may need to change their code 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 `yspec_free()` - replace with `ys_free()`
* Removed `endtag` parameter of `clixon_xml_parse_file()` * Removed `endtag` parameter of `clixon_xml_parse_file()`
* Restconf authentication callback (ca_auth) signature changed (again) * Restconf authentication callback (ca_auth) signature changed (again)

View file

@ -499,6 +499,10 @@ cli_debug_backend(clicon_handle h,
* @param[in] arg Else use the integer value of argument * @param[in] arg Else use the integer value of argument
* @note The level is either what is specified in arg as int 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. * _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 <restconf> 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 int
cli_debug_restconf(clicon_handle h, cli_debug_restconf(clicon_handle h,
@ -518,8 +522,7 @@ cli_debug_restconf(clicon_handle h,
} }
level = cv_int32_get(cv); level = cv_int32_get(cv);
/* restconf daemon */ /* restconf daemon */
if (0) /* XXX notyet */ retval = clicon_rpc_restconf_debug(h, level);
retval = clicon_rpc_debug(h, level);
done: done:
return retval; return retval;
} }
@ -1302,32 +1305,6 @@ cli_copy_config(clicon_handle h,
return retval; 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 int
cli_help(clicon_handle h, cvec *vars, cvec *argv) cli_help(clicon_handle h, cvec *vars, cvec *argv)
{ {

View file

@ -979,8 +979,14 @@ cx_evhtp_init(clicon_handle h,
(bstr = xml_body(x)) != NULL){ (bstr = xml_body(x)) != NULL){
dbg = atoi(bstr); dbg = atoi(bstr);
clicon_debug_init(dbg, NULL); 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 :-( */ /* Here the daemon either uses SSL or not, ie you cant seem to mix http and https :-( */
if (ssl_enable){ if (ssl_enable){
/* Init evhtp ssl config struct */ /* Init evhtp ssl config struct */

View file

@ -68,19 +68,43 @@ How to debug
CFLAGS="-g -Wall" INSTALLFLAGS="" ./configure CFLAGS="-g -Wall" INSTALLFLAGS="" ./configure
``` ```
### Set backend debug using curl ### Set backend debug
Set backend debug using rpc Using netconf:
```
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><debug xmlns="http://clicon.org/lib"><level>1</level></debug></rpc>
```
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}}' 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 <restconf> 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 <<EOF
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><edit-config><target><candidate/></target><config><restconf xmlns="http://clicon.org/restconf"><debug>1</debug></restconf></config></edit-config></rpc>]]>]]>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><commit/></rpc>]]>]]>
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"}}' 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. ### Make your own simplified yang and configuration file.
``` ```

View file

@ -62,6 +62,7 @@ int clicon_rpc_commit(clicon_handle h);
int clicon_rpc_discard_changes(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_create_subscription(clicon_handle h, char *stream, char *filter, int *s);
int clicon_rpc_debug(clicon_handle h, int level); 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); int clicon_hello_req(clicon_handle h, uint32_t *id);
#endif /* _CLIXON_PROTO_CLIENT_H_ */ #endif /* _CLIXON_PROTO_CLIENT_H_ */

View file

@ -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_cb(FILE *f, yang_stmt *yn, clicon_output_cb *fn);
int yang_print(FILE *f, yang_stmt *yn); int yang_print(FILE *f, yang_stmt *yn);
int yang_print_cbuf(cbuf *cb, yang_stmt *yn, int marginal); 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 if_feature(yang_stmt *yspec, char *module, char *feature);
int ys_populate(yang_stmt *ys, void *arg); int ys_populate(yang_stmt *ys, void *arg);
int ys_populate2(yang_stmt *ys, void *arg); int ys_populate2(yang_stmt *ys, void *arg);

View file

@ -1164,6 +1164,57 @@ clicon_rpc_debug(clicon_handle h,
return retval; 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 <restconf> 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,
"<rpc xmlns=\"%s\" username=\"%s\"><edit-config><target><candidate/></target><config><restconf xmlns=\"%s\"><debug>%d</debug></restconf></config></edit-config></rpc>",
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 /*! Send a hello request to the backend server
* @param[in] h CLICON handle * @param[in] h CLICON handle
* @param[in] level Debug level * @param[in] level Debug level

View file

@ -1466,6 +1466,40 @@ yang_print(FILE *f,
return yang_print_cb(f, yn, fprintf); 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 /*! Print yang specification to cligen buf
* @param[in] cb Cligen buffer. This is where the pretty print is. * @param[in] cb Cligen buffer. This is where the pretty print is.
* @param[in] yn Yang node to print * @param[in] yn Yang node to print

View file

@ -14,6 +14,7 @@
# (4) local/backend config. Evhtp only # (4) local/backend config. Evhtp only
# - The tests runs through both (if compiled with evhtp) # - The tests runs through both (if compiled with evhtp)
# See also test_restconf2.sh # 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) # Magic line must be first in script (see README.md)
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Restconf direct start/stop using RPC and config enable flag (as alternative to systemd or other) # 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 start, if enable is true, start the service, if false, error or ignore it
# - on RPC stop, stop the service # - on RPC stop, stop the service
# - on backend start make the state as configured # - on backend start make the state as configured