xml config default; api_path_fmt2api_path cleanup
This commit is contained in:
parent
e1b7ea8449
commit
5cea5fa768
10 changed files with 165 additions and 70 deletions
|
|
@ -250,6 +250,7 @@ main(int argc, char **argv)
|
|||
/* Initiate CLICON handle */
|
||||
if ((h = cli_handle_init()) == NULL)
|
||||
goto done;
|
||||
|
||||
if (cli_plugin_init(h) != 0)
|
||||
goto done;
|
||||
once = 0;
|
||||
|
|
@ -486,6 +487,7 @@ main(int argc, char **argv)
|
|||
// Gets in your face if we log on stderr
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
||||
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
||||
if (h)
|
||||
cli_terminate(h);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -99,7 +99,8 @@ expand_dbvar(void *h,
|
|||
cvec *helptexts)
|
||||
{
|
||||
int retval = -1;
|
||||
char *api_path;
|
||||
char *api_path_fmt;
|
||||
char *api_path = NULL;
|
||||
char *dbstr;
|
||||
cxobj *xt = NULL;
|
||||
char *xpath = NULL;
|
||||
|
|
@ -145,13 +146,16 @@ expand_dbvar(void *h,
|
|||
clicon_err(OE_PLUGIN, 0, "%s: Error when accessing argument <api_path>");
|
||||
goto done;
|
||||
}
|
||||
api_path = cv_string_get(cv);
|
||||
/* api_path = /interface/%s/address/%s
|
||||
api_path_fmt = cv_string_get(cv);
|
||||
/* api_path_fmt = /interface/%s/address/%s
|
||||
--> ^/interface/eth0/address/.*$
|
||||
--> /interface/[name=eth0]/address
|
||||
*/
|
||||
if (api_path_fmt2xpath(api_path, cvv, &xpath) < 0)
|
||||
if (api_path_fmt2xpath(api_path_fmt, cvv, &xpath) < 0)
|
||||
goto done;
|
||||
if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0)
|
||||
goto done;
|
||||
|
||||
/* XXX read whole configuration, why not send xpath? */
|
||||
if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0)
|
||||
goto done;
|
||||
|
|
@ -165,7 +169,7 @@ expand_dbvar(void *h,
|
|||
if ((xtop = xml_new("config", NULL)) == NULL)
|
||||
goto done;
|
||||
xbot = xtop;
|
||||
/* This is primarily to get "y", XXX xbot can be broken (contains =%s)
|
||||
/* This is primarily to get "y",
|
||||
* xpath2xml would have worked!!
|
||||
*/
|
||||
if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0)
|
||||
|
|
@ -236,6 +240,8 @@ expand_dbvar(void *h,
|
|||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (api_path)
|
||||
free(api_path);
|
||||
if (xvec)
|
||||
free(xvec);
|
||||
if (xtop)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ sudo /etc/init.d nginx start
|
|||
|
||||
Start clixon restconf daemon
|
||||
```
|
||||
olof@vandal> sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/routing.conf " -s /bin/sh www-data
|
||||
olof@vandal> sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/routing.xml " -s /bin/sh www-data
|
||||
```
|
||||
|
||||
Make restconf calls with curl
|
||||
|
|
@ -67,7 +67,7 @@ curl -sX POST -d '{"interfaces":{"interface":{"name":"eth1","type":"eth","enable
|
|||
|
||||
Start the restconf fastcgi program with debug flag:
|
||||
```
|
||||
sudo su -c "/www-data/clixon_restconf -Df /usr/local/etc/routing.conf" -s /bin/sh www-data
|
||||
sudo su -c "/www-data/clixon_restconf -Df /usr/local/etc/routing.xml" -s /bin/sh www-data
|
||||
```
|
||||
Look at syslog:
|
||||
```
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
* sudo apt-get install libfcgi-dev
|
||||
* gcc -o fastcgi fastcgi.c -lfcgi
|
||||
|
||||
* sudo su -c "/www-data/clixon_restconf -Df /usr/local/etc/routing.conf " -s /bin/sh www-data
|
||||
* sudo su -c "/www-data/clixon_restconf -Df /usr/local/etc/routing.xml " -s /bin/sh www-data
|
||||
|
||||
* This is the interface:
|
||||
* api/data/profile=<name>/metric=<name> PUT data:enable=<flag>
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@
|
|||
* sudo apt-get install libfcgi-dev
|
||||
* gcc -o fastcgi fastcgi.c -lfcgi
|
||||
|
||||
* sudo su -c "/www-data/clixon_restconf -Df /usr/local/etc/routing.conf " -s /bin/sh www-data
|
||||
* sudo su -c "/www-data/clixon_restconf -Df /usr/local/etc/routing.xml " -s /bin/sh www-data
|
||||
|
||||
* This is the interface:
|
||||
* api/data/profile=<name>/metric=<name> PUT data:enable=<flag>
|
||||
|
|
|
|||
19
doc/FAQ.md
19
doc/FAQ.md
|
|
@ -59,9 +59,9 @@ Build using 'make doc' and aim your browser at doc/html/index.html or
|
|||
use the web resource: http://clicon.org/ref/index.html
|
||||
|
||||
## How do you run the example?
|
||||
- Start a backend server: 'clixon_backend -Ff /usr/local/etc/routing.conf'
|
||||
- Start a cli session: clixon_cli -f /usr/local/etc/routing.conf
|
||||
- Start a netconf session: clixon_netconf -f /usr/local/etc/routing.conf
|
||||
- Start a backend server: 'clixon_backend -Ff /usr/local/etc/routing.xml'
|
||||
- Start a cli session: clixon_cli -f /usr/local/etc/routing.xml
|
||||
- Start a netconf session: clixon_netconf -f /usr/local/etc/routing.xml
|
||||
|
||||
## How is configuration data stored?
|
||||
Configuration data is stored in an XML datastore. The default is a
|
||||
|
|
@ -82,10 +82,7 @@ is the core functionality of a clixon system.
|
|||
## What is a Clixon configuration file?
|
||||
Clixon options are stored in a configuration file you must specify
|
||||
when you start a backend or client using -f. The example configuration
|
||||
file is /usr/local/etc/routing.conf.
|
||||
This file is generated from the base source clixon.conf.cpp.cpp and
|
||||
is merged with local configuration files, such as routing.conf.local.
|
||||
This is slightly confusing and could be improved.
|
||||
file is installed at /usr/local/etc/routing.xml.
|
||||
|
||||
## Can I run Clixon as docker containers?
|
||||
Yes, the example works as docker containers as well. backend and cli needs a
|
||||
|
|
@ -107,12 +104,12 @@ You may also push the containers with 'make push' but you may then consider chan
|
|||
|
||||
As an alternative to cli configuration, you can use netconf. Easiest is to just pipe netconf commands to the clixon_netconf application.
|
||||
Example:
|
||||
echo "<rpc><get-config><source><candidate/></source><configuration/></get-config></rpc>]]>]]>" | clixon_netconf -f /usr/local/etc/routing.conf
|
||||
echo "<rpc><get-config><source><candidate/></source><configuration/></get-config></rpc>]]>]]>" | clixon_netconf -f /usr/local/etc/routing.xml
|
||||
|
||||
However, more useful is to run clixon_netconf as an SSH
|
||||
subsystem. Register the subsystem in /etc/sshd_config:
|
||||
```
|
||||
Subsystem netconf /usr/local/bin/clixon_netconf -f /usr/local/etc/routing.conf
|
||||
Subsystem netconf /usr/local/bin/clixon_netconf -f /usr/local/etc/routing.xml
|
||||
```
|
||||
and then invoke it from a client using
|
||||
```
|
||||
|
|
@ -147,7 +144,7 @@ cli>
|
|||
```
|
||||
or via netconf:
|
||||
```
|
||||
clixon_netconf -qf /usr/local/etc/routing.conf
|
||||
clixon_netconf -qf /usr/local/etc/routing.xml
|
||||
<rpc><create-subscription><stream>ROUTING</stream></create-subscription></rpc>]]>]]>
|
||||
<rpc-reply><ok/></rpc-reply>]]>]]>
|
||||
<notification><event>Routing notification</event></notification>]]>]]>
|
||||
|
|
@ -156,7 +153,7 @@ clixon_netconf -qf /usr/local/etc/routing.conf
|
|||
```
|
||||
|
||||
## I want to program. How do I extend the example?
|
||||
- routing.conf.local - Override default settings
|
||||
- routing.xml - Change the configuration file
|
||||
- The yang specifications - This is the central part. It changes the XML, database and the config cli.
|
||||
- routing_cli.cli - Change the fixed part of the CLI commands
|
||||
- routing_cli.c - Cli C-commands are placed here.
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@
|
|||
```
|
||||
Start backend:
|
||||
```
|
||||
clixon_backend -f /usr/local/etc/routing.conf -I
|
||||
clixon_backend -f /usr/local/etc/routing.xml -I
|
||||
```
|
||||
Edit cli:
|
||||
```
|
||||
clixon_cli -f /usr/local/etc/routing.conf
|
||||
clixon_cli -f /usr/local/etc/routing.xml
|
||||
```
|
||||
Send netconf command:
|
||||
```
|
||||
clixon_netconf -f /usr/local/etc/routing.conf
|
||||
clixon_netconf -f /usr/local/etc/routing.xml
|
||||
```
|
||||
|
||||
## Setting data example using netconf
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<config>
|
||||
<CLICON_CONFIGFILE>/usr/local/etc/routing.conf</CLICON_CONFIGFILE>
|
||||
<CLICON_CONFIGFILE>/usr/local/etc/routing.xml</CLICON_CONFIGFILE>
|
||||
<CLICON_YANG_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||
<CLICON_CLI_MODE>routing</CLICON_CLI_MODE>
|
||||
|
|
|
|||
|
|
@ -993,15 +993,21 @@ yang2api_path_fmt(yang_stmt *ys,
|
|||
/*! Transform an xml key format and a vector of values to an XML key
|
||||
* Used for actual key, eg in clicon_rpc_change(), xmldb_put_xkey()
|
||||
* Example:
|
||||
* xmlkeyfmt: /aaa/%s/name
|
||||
* cvv: key=17
|
||||
* xmlkey: /aaa/17/name
|
||||
* xmlkeyfmt: /interfaces/interface=%s/ipv4/address=%s
|
||||
* cvv: 0 : set interfaces interface e ipv4 address 1.2.3.4
|
||||
* 1 : name = "e"
|
||||
* 2 : ip = "1.2.3.4"
|
||||
* api_path: /interfaces/interface=e/ipv4/address=1.2.3.4
|
||||
* @param[in] api_path_fmt XML key format, eg /aaa/%s/name
|
||||
* @param[in] cvv cligen variable vector, one for every wildchar in api_path_fmt
|
||||
* @param[in] cvv cligen variable vector, one for every wildchar in
|
||||
* api_path_fmt
|
||||
* @param[out] api_path api_path, eg /aaa/17. Free after use
|
||||
* @param[out] yang_arg yang-stmt argument name. Free after use
|
||||
* @note first and last elements of cvv are not used,..
|
||||
* @see cli_dbxml where this function is called
|
||||
* @see api_path_fmt2xpath
|
||||
*
|
||||
* /interfaces/interface=%s/name --> /interfaces/interface/name
|
||||
* /interfaces/interface=%s/ipv4/address=%s --> /interfaces/interface=e/ipv4/address
|
||||
*/
|
||||
int
|
||||
api_path_fmt2api_path(char *api_path_fmt,
|
||||
|
|
@ -1016,19 +1022,19 @@ api_path_fmt2api_path(char *api_path_fmt,
|
|||
int j;
|
||||
char *str;
|
||||
char *strenc=NULL;
|
||||
cg_var *cv;
|
||||
|
||||
#if 1
|
||||
/* Sanity check */
|
||||
#if 0
|
||||
j = 0; /* Count % */
|
||||
for (i=0; i<strlen(api_path_fmt); i++)
|
||||
if (api_path_fmt[i] == '%')
|
||||
j++;
|
||||
if (j+2 < cvec_len(cvv)) {
|
||||
clicon_log(LOG_WARNING, "%s xmlkey format string mismatch(j=%d, cvec_len=%d): %s",
|
||||
if (j > cvec_len(cvv)) { //cvec_len can be longer
|
||||
clicon_log(LOG_WARNING, "%s api_path_fmt number of %% is %d, does not match number of cvv entries %d",
|
||||
api_path_fmt,
|
||||
j,
|
||||
cvec_len(cvv),
|
||||
cv_string_get(cvec_i(cvv, 0)));
|
||||
cvec_len(cvv));
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1043,8 +1049,12 @@ api_path_fmt2api_path(char *api_path_fmt,
|
|||
esc = 0;
|
||||
if (c!='s')
|
||||
continue;
|
||||
if ((str = cv2str_dup(cvec_i(cvv, j++))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
if (j == cvec_len(cvv)) /* last element */
|
||||
;
|
||||
else{
|
||||
cv = cvec_i(cvv, j++);
|
||||
if ((str = cv2str_dup(cv)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||
goto done;
|
||||
}
|
||||
if (percent_encode(str, &strenc) < 0)
|
||||
|
|
@ -1053,15 +1063,17 @@ api_path_fmt2api_path(char *api_path_fmt,
|
|||
free(strenc); strenc = NULL;
|
||||
free(str); str = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (c == '%')
|
||||
esc++;
|
||||
else if (c == '/'){
|
||||
cprintf(cb, "%c", c);
|
||||
}
|
||||
else{
|
||||
if ((c == '=' || c == ',') && api_path_fmt[i+1]=='%' && j == cvec_len(cvv))
|
||||
; /* skip */
|
||||
else
|
||||
cprintf(cb, "%c", c);
|
||||
}
|
||||
}
|
||||
if ((*api_path = strdup(cbuf_get(cb))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
|
|
@ -1073,12 +1085,12 @@ api_path_fmt2api_path(char *api_path_fmt,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Transform an xml key format and a vector of values to an XML path
|
||||
* Used to input xmldb_get() or xmldb_get_vec
|
||||
* Add .* in last %s position.
|
||||
* Example:
|
||||
* xmlkeyfmt: /interface/%s/address/%s OLDXXX
|
||||
* xmlkeyfmt: /interface=%s/address=%s
|
||||
* api_path_fmt: /interface/%s/address/%s
|
||||
* cvv: name=eth0
|
||||
* xmlkey: /interface/[name=eth0]/address
|
||||
* Example2:
|
||||
|
|
@ -1102,21 +1114,20 @@ api_path_fmt2xpath(char *api_path_fmt,
|
|||
int j;
|
||||
char *str;
|
||||
cg_var *cv;
|
||||
int skip = 0;
|
||||
|
||||
/* Sanity check: count '%' */
|
||||
#if 0
|
||||
#if 1
|
||||
j = 0; /* Count % */
|
||||
for (i=0; i<strlen(api_path_fmt); i++)
|
||||
if (api_path_fmt[i] == '%')
|
||||
j++;
|
||||
if (j < cvec_len(cvv)-1) {
|
||||
if (j > cvec_len(cvv)) {
|
||||
clicon_log(LOG_WARNING, "%s xmlkey format string mismatch(j=%d, cvec_len=%d): %s",
|
||||
api_path_fmt,
|
||||
j,
|
||||
cvec_len(cvv),
|
||||
cv_string_get(cvec_i(cvv, 0)));
|
||||
// goto done;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
|
|
@ -1130,9 +1141,7 @@ api_path_fmt2xpath(char *api_path_fmt,
|
|||
esc = 0;
|
||||
if (c!='s')
|
||||
continue;
|
||||
|
||||
if (j == cvec_len(cvv)) /* last element */
|
||||
//skip++;
|
||||
;
|
||||
else{
|
||||
cv = cvec_i(cvv, j++);
|
||||
|
|
@ -1148,9 +1157,6 @@ api_path_fmt2xpath(char *api_path_fmt,
|
|||
if (c == '%')
|
||||
esc++;
|
||||
else{
|
||||
if (skip)
|
||||
skip=0;
|
||||
else
|
||||
if ((c == '=' || c == ',') && api_path_fmt[i+1]=='%')
|
||||
; /* skip */
|
||||
else
|
||||
|
|
@ -1687,7 +1693,7 @@ api_path2xml_vec(char **vec,
|
|||
}
|
||||
switch (y->ys_keyword){
|
||||
case Y_LEAF_LIST:
|
||||
if (restval==NULL){
|
||||
if (0 && restval==NULL){
|
||||
clicon_err(OE_XML, 0, "malformed key, expected '=<restval>'");
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -1697,7 +1703,7 @@ api_path2xml_vec(char **vec,
|
|||
if ((xb = xml_new("body", x)) == NULL)
|
||||
goto done;
|
||||
xml_type_set(xb, CX_BODY);
|
||||
if (xml_value_set(xb, restval) < 0)
|
||||
if (restval && xml_value_set(xb, restval) < 0)
|
||||
goto done;
|
||||
break;
|
||||
case Y_LIST:
|
||||
|
|
@ -1983,3 +1989,70 @@ done:
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turn this on for uni-test programs
|
||||
* Usage: clixon_string join
|
||||
* Example compile:
|
||||
gcc -g -o clixon_xml_map -I. -I../clixon ./clixon_xml_map.c -lclixon -lcligen
|
||||
* Example run:
|
||||
/interfaces/interface=%s/name --> interfaces/interface/name
|
||||
/interfaces/interface=%s/ipv4/address=%s e --> /interfaces/interface=e/ipv4/address
|
||||
/interfaces/interface=%s,%s/ipv4/address=%s e f --> /interfaces/interface=e,f/ipv4/address
|
||||
/interfaces/interface=%s/ipv4/address=%s,%s e f --> /interfaces/interface=e/ipv4/address=f
|
||||
|
||||
/interfaces/interface=%s/ipv4/address=%s/prefix-length eth 1.2.3.4 -->
|
||||
/interfaces/interface=eth/ipv4/address=1.2.3.4/prefix-length
|
||||
|
||||
*/
|
||||
#if 0 /* Test program */
|
||||
|
||||
static int
|
||||
usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "usage:%s <api_path_fmt> <cv0>, <cv1>,...\n", argv0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int nvec;
|
||||
char **vec;
|
||||
char *str0;
|
||||
char *str1;
|
||||
int i;
|
||||
char *api_path_fmt;
|
||||
cg_var *cv;
|
||||
cvec *cvv;
|
||||
char *api_path=NULL;
|
||||
|
||||
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
|
||||
if (argc < 2){
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
api_path_fmt = argv[1];
|
||||
if ((cvv = cvec_new(0)) == NULL){
|
||||
perror("cvec_new");
|
||||
return -1;
|
||||
}
|
||||
cv = cv_new(CGV_STRING);
|
||||
cv_string_set(cv, "CLI base command");
|
||||
cvec_append_var(cvv, cv);
|
||||
for (i=2; i<argc; i++){
|
||||
cv = cv_new(CGV_STRING);
|
||||
if (cv_parse(argv[i], cv) < 0){
|
||||
perror("cv_parse");
|
||||
return -1;
|
||||
}
|
||||
cvec_append_var(cvv, cv);
|
||||
}
|
||||
if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0)
|
||||
return -1;
|
||||
printf("%s\n", api_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* Test program */
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,17 @@ module example{
|
|||
}
|
||||
}
|
||||
}
|
||||
list sender{
|
||||
key name;
|
||||
leaf name{
|
||||
type string;
|
||||
}
|
||||
leaf template{
|
||||
type leafref{
|
||||
path "/sender/name";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
@ -96,6 +107,12 @@ expectfn "$clixon_cli -1f $clixon_cf -y /tmp/leafref.yang -l o set default-addre
|
|||
new "cli leafref validate"
|
||||
expectfn "$clixon_cli -1f $clixon_cf -y /tmp/leafref.yang -l o validate" "^$"
|
||||
|
||||
new "cli sender"
|
||||
expectfn "$clixon_cli -1f $clixon_cf -y /tmp/leafref.yang -l o set sender a" "^$"
|
||||
|
||||
new "cli sender template"
|
||||
expectfn "$clixon_cli -1f $clixon_cf -y /tmp/leafref.yang -l o set sender b template a" "^$"
|
||||
|
||||
new "Kill backend"
|
||||
# Check if still alive
|
||||
pid=`pgrep clixon_backend`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue