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 */
|
/* Initiate CLICON handle */
|
||||||
if ((h = cli_handle_init()) == NULL)
|
if ((h = cli_handle_init()) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
if (cli_plugin_init(h) != 0)
|
if (cli_plugin_init(h) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
once = 0;
|
once = 0;
|
||||||
|
|
@ -486,6 +487,7 @@ main(int argc, char **argv)
|
||||||
// Gets in your face if we log on stderr
|
// Gets in your face if we log on stderr
|
||||||
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
clicon_log_init(__PROGRAM__, LOG_INFO, 0); /* Log on syslog no stderr */
|
||||||
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
clicon_log(LOG_NOTICE, "%s: %u Terminated\n", __PROGRAM__, getpid());
|
||||||
|
if (h)
|
||||||
cli_terminate(h);
|
cli_terminate(h);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,8 @@ expand_dbvar(void *h,
|
||||||
cvec *helptexts)
|
cvec *helptexts)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *api_path;
|
char *api_path_fmt;
|
||||||
|
char *api_path = NULL;
|
||||||
char *dbstr;
|
char *dbstr;
|
||||||
cxobj *xt = NULL;
|
cxobj *xt = NULL;
|
||||||
char *xpath = NULL;
|
char *xpath = NULL;
|
||||||
|
|
@ -145,13 +146,16 @@ expand_dbvar(void *h,
|
||||||
clicon_err(OE_PLUGIN, 0, "%s: Error when accessing argument <api_path>");
|
clicon_err(OE_PLUGIN, 0, "%s: Error when accessing argument <api_path>");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
api_path = cv_string_get(cv);
|
api_path_fmt = cv_string_get(cv);
|
||||||
/* api_path = /interface/%s/address/%s
|
/* api_path_fmt = /interface/%s/address/%s
|
||||||
--> ^/interface/eth0/address/.*$
|
--> ^/interface/eth0/address/.*$
|
||||||
--> /interface/[name=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;
|
goto done;
|
||||||
|
if (api_path_fmt2api_path(api_path_fmt, cvv, &api_path) < 0)
|
||||||
|
goto done;
|
||||||
|
|
||||||
/* XXX read whole configuration, why not send xpath? */
|
/* XXX read whole configuration, why not send xpath? */
|
||||||
if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0)
|
if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -165,7 +169,7 @@ expand_dbvar(void *h,
|
||||||
if ((xtop = xml_new("config", NULL)) == NULL)
|
if ((xtop = xml_new("config", NULL)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
xbot = xtop;
|
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!!
|
* xpath2xml would have worked!!
|
||||||
*/
|
*/
|
||||||
if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0)
|
if (api_path && api_path2xml(api_path, yspec, xtop, 0, &xbot, &y) < 0)
|
||||||
|
|
@ -236,6 +240,8 @@ expand_dbvar(void *h,
|
||||||
}
|
}
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
|
if (api_path)
|
||||||
|
free(api_path);
|
||||||
if (xvec)
|
if (xvec)
|
||||||
free(xvec);
|
free(xvec);
|
||||||
if (xtop)
|
if (xtop)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ sudo /etc/init.d nginx start
|
||||||
|
|
||||||
Start clixon restconf daemon
|
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
|
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:
|
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:
|
Look at syslog:
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
* sudo apt-get install libfcgi-dev
|
* sudo apt-get install libfcgi-dev
|
||||||
* gcc -o fastcgi fastcgi.c -lfcgi
|
* 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:
|
* This is the interface:
|
||||||
* api/data/profile=<name>/metric=<name> PUT data:enable=<flag>
|
* api/data/profile=<name>/metric=<name> PUT data:enable=<flag>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
* sudo apt-get install libfcgi-dev
|
* sudo apt-get install libfcgi-dev
|
||||||
* gcc -o fastcgi fastcgi.c -lfcgi
|
* 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:
|
* This is the interface:
|
||||||
* api/data/profile=<name>/metric=<name> PUT data:enable=<flag>
|
* 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
|
use the web resource: http://clicon.org/ref/index.html
|
||||||
|
|
||||||
## How do you run the example?
|
## How do you run the example?
|
||||||
- Start a backend server: 'clixon_backend -Ff /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.conf
|
- Start a cli session: clixon_cli -f /usr/local/etc/routing.xml
|
||||||
- Start a netconf session: clixon_netconf -f /usr/local/etc/routing.conf
|
- Start a netconf session: clixon_netconf -f /usr/local/etc/routing.xml
|
||||||
|
|
||||||
## How is configuration data stored?
|
## How is configuration data stored?
|
||||||
Configuration data is stored in an XML datastore. The default is a
|
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?
|
## What is a Clixon configuration file?
|
||||||
Clixon options are stored in a configuration file you must specify
|
Clixon options are stored in a configuration file you must specify
|
||||||
when you start a backend or client using -f. The example configuration
|
when you start a backend or client using -f. The example configuration
|
||||||
file is /usr/local/etc/routing.conf.
|
file is installed at /usr/local/etc/routing.xml.
|
||||||
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.
|
|
||||||
|
|
||||||
## Can I run Clixon as docker containers?
|
## Can I run Clixon as docker containers?
|
||||||
Yes, the example works as docker containers as well. backend and cli needs a
|
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.
|
As an alternative to cli configuration, you can use netconf. Easiest is to just pipe netconf commands to the clixon_netconf application.
|
||||||
Example:
|
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
|
However, more useful is to run clixon_netconf as an SSH
|
||||||
subsystem. Register the subsystem in /etc/sshd_config:
|
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
|
and then invoke it from a client using
|
||||||
```
|
```
|
||||||
|
|
@ -147,7 +144,7 @@ cli>
|
||||||
```
|
```
|
||||||
or via netconf:
|
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><create-subscription><stream>ROUTING</stream></create-subscription></rpc>]]>]]>
|
||||||
<rpc-reply><ok/></rpc-reply>]]>]]>
|
<rpc-reply><ok/></rpc-reply>]]>]]>
|
||||||
<notification><event>Routing notification</event></notification>]]>]]>
|
<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?
|
## 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.
|
- 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.cli - Change the fixed part of the CLI commands
|
||||||
- routing_cli.c - Cli C-commands are placed here.
|
- routing_cli.c - Cli C-commands are placed here.
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,15 @@
|
||||||
```
|
```
|
||||||
Start backend:
|
Start backend:
|
||||||
```
|
```
|
||||||
clixon_backend -f /usr/local/etc/routing.conf -I
|
clixon_backend -f /usr/local/etc/routing.xml -I
|
||||||
```
|
```
|
||||||
Edit cli:
|
Edit cli:
|
||||||
```
|
```
|
||||||
clixon_cli -f /usr/local/etc/routing.conf
|
clixon_cli -f /usr/local/etc/routing.xml
|
||||||
```
|
```
|
||||||
Send netconf command:
|
Send netconf command:
|
||||||
```
|
```
|
||||||
clixon_netconf -f /usr/local/etc/routing.conf
|
clixon_netconf -f /usr/local/etc/routing.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Setting data example using netconf
|
## Setting data example using netconf
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<config>
|
<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_DIR>/usr/local/share/routing/yang</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||||
<CLICON_CLI_MODE>routing</CLICON_CLI_MODE>
|
<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
|
/*! 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()
|
* Used for actual key, eg in clicon_rpc_change(), xmldb_put_xkey()
|
||||||
* Example:
|
* Example:
|
||||||
* xmlkeyfmt: /aaa/%s/name
|
* xmlkeyfmt: /interfaces/interface=%s/ipv4/address=%s
|
||||||
* cvv: key=17
|
* cvv: 0 : set interfaces interface e ipv4 address 1.2.3.4
|
||||||
* xmlkey: /aaa/17/name
|
* 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] 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] api_path api_path, eg /aaa/17. Free after use
|
||||||
* @param[out] yang_arg yang-stmt argument name. Free after use
|
* @param[out] yang_arg yang-stmt argument name. Free after use
|
||||||
* @note first and last elements of cvv are not used,..
|
* @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
|
int
|
||||||
api_path_fmt2api_path(char *api_path_fmt,
|
api_path_fmt2api_path(char *api_path_fmt,
|
||||||
|
|
@ -1016,19 +1022,19 @@ api_path_fmt2api_path(char *api_path_fmt,
|
||||||
int j;
|
int j;
|
||||||
char *str;
|
char *str;
|
||||||
char *strenc=NULL;
|
char *strenc=NULL;
|
||||||
|
cg_var *cv;
|
||||||
|
|
||||||
|
#if 1
|
||||||
/* Sanity check */
|
/* Sanity check */
|
||||||
#if 0
|
|
||||||
j = 0; /* Count % */
|
j = 0; /* Count % */
|
||||||
for (i=0; i<strlen(api_path_fmt); i++)
|
for (i=0; i<strlen(api_path_fmt); i++)
|
||||||
if (api_path_fmt[i] == '%')
|
if (api_path_fmt[i] == '%')
|
||||||
j++;
|
j++;
|
||||||
if (j+2 < cvec_len(cvv)) {
|
if (j > cvec_len(cvv)) { //cvec_len can be longer
|
||||||
clicon_log(LOG_WARNING, "%s xmlkey format string mismatch(j=%d, cvec_len=%d): %s",
|
clicon_log(LOG_WARNING, "%s api_path_fmt number of %% is %d, does not match number of cvv entries %d",
|
||||||
api_path_fmt,
|
api_path_fmt,
|
||||||
j,
|
j,
|
||||||
cvec_len(cvv),
|
cvec_len(cvv));
|
||||||
cv_string_get(cvec_i(cvv, 0)));
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1043,8 +1049,12 @@ api_path_fmt2api_path(char *api_path_fmt,
|
||||||
esc = 0;
|
esc = 0;
|
||||||
if (c!='s')
|
if (c!='s')
|
||||||
continue;
|
continue;
|
||||||
if ((str = cv2str_dup(cvec_i(cvv, j++))) == NULL){
|
if (j == cvec_len(cvv)) /* last element */
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
;
|
||||||
|
else{
|
||||||
|
cv = cvec_i(cvv, j++);
|
||||||
|
if ((str = cv2str_dup(cv)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "cv2str_dup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (percent_encode(str, &strenc) < 0)
|
if (percent_encode(str, &strenc) < 0)
|
||||||
|
|
@ -1053,15 +1063,17 @@ api_path_fmt2api_path(char *api_path_fmt,
|
||||||
free(strenc); strenc = NULL;
|
free(strenc); strenc = NULL;
|
||||||
free(str); str = NULL;
|
free(str); str = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
if (c == '%')
|
if (c == '%')
|
||||||
esc++;
|
esc++;
|
||||||
else if (c == '/'){
|
else{
|
||||||
cprintf(cb, "%c", c);
|
if ((c == '=' || c == ',') && api_path_fmt[i+1]=='%' && j == cvec_len(cvv))
|
||||||
}
|
; /* skip */
|
||||||
else
|
else
|
||||||
cprintf(cb, "%c", c);
|
cprintf(cb, "%c", c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if ((*api_path = strdup(cbuf_get(cb))) == NULL){
|
if ((*api_path = strdup(cbuf_get(cb))) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -1073,12 +1085,12 @@ api_path_fmt2api_path(char *api_path_fmt,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Transform an xml key format and a vector of values to an XML path
|
/*! Transform an xml key format and a vector of values to an XML path
|
||||||
* Used to input xmldb_get() or xmldb_get_vec
|
* Used to input xmldb_get() or xmldb_get_vec
|
||||||
* Add .* in last %s position.
|
* Add .* in last %s position.
|
||||||
* Example:
|
* Example:
|
||||||
* xmlkeyfmt: /interface/%s/address/%s OLDXXX
|
* api_path_fmt: /interface/%s/address/%s
|
||||||
* xmlkeyfmt: /interface=%s/address=%s
|
|
||||||
* cvv: name=eth0
|
* cvv: name=eth0
|
||||||
* xmlkey: /interface/[name=eth0]/address
|
* xmlkey: /interface/[name=eth0]/address
|
||||||
* Example2:
|
* Example2:
|
||||||
|
|
@ -1102,21 +1114,20 @@ api_path_fmt2xpath(char *api_path_fmt,
|
||||||
int j;
|
int j;
|
||||||
char *str;
|
char *str;
|
||||||
cg_var *cv;
|
cg_var *cv;
|
||||||
int skip = 0;
|
|
||||||
|
|
||||||
/* Sanity check: count '%' */
|
/* Sanity check: count '%' */
|
||||||
#if 0
|
#if 1
|
||||||
j = 0; /* Count % */
|
j = 0; /* Count % */
|
||||||
for (i=0; i<strlen(api_path_fmt); i++)
|
for (i=0; i<strlen(api_path_fmt); i++)
|
||||||
if (api_path_fmt[i] == '%')
|
if (api_path_fmt[i] == '%')
|
||||||
j++;
|
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",
|
clicon_log(LOG_WARNING, "%s xmlkey format string mismatch(j=%d, cvec_len=%d): %s",
|
||||||
api_path_fmt,
|
api_path_fmt,
|
||||||
j,
|
j,
|
||||||
cvec_len(cvv),
|
cvec_len(cvv),
|
||||||
cv_string_get(cvec_i(cvv, 0)));
|
cv_string_get(cvec_i(cvv, 0)));
|
||||||
// goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((cb = cbuf_new()) == NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
|
|
@ -1130,9 +1141,7 @@ api_path_fmt2xpath(char *api_path_fmt,
|
||||||
esc = 0;
|
esc = 0;
|
||||||
if (c!='s')
|
if (c!='s')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (j == cvec_len(cvv)) /* last element */
|
if (j == cvec_len(cvv)) /* last element */
|
||||||
//skip++;
|
|
||||||
;
|
;
|
||||||
else{
|
else{
|
||||||
cv = cvec_i(cvv, j++);
|
cv = cvec_i(cvv, j++);
|
||||||
|
|
@ -1148,9 +1157,6 @@ api_path_fmt2xpath(char *api_path_fmt,
|
||||||
if (c == '%')
|
if (c == '%')
|
||||||
esc++;
|
esc++;
|
||||||
else{
|
else{
|
||||||
if (skip)
|
|
||||||
skip=0;
|
|
||||||
else
|
|
||||||
if ((c == '=' || c == ',') && api_path_fmt[i+1]=='%')
|
if ((c == '=' || c == ',') && api_path_fmt[i+1]=='%')
|
||||||
; /* skip */
|
; /* skip */
|
||||||
else
|
else
|
||||||
|
|
@ -1687,7 +1693,7 @@ api_path2xml_vec(char **vec,
|
||||||
}
|
}
|
||||||
switch (y->ys_keyword){
|
switch (y->ys_keyword){
|
||||||
case Y_LEAF_LIST:
|
case Y_LEAF_LIST:
|
||||||
if (restval==NULL){
|
if (0 && restval==NULL){
|
||||||
clicon_err(OE_XML, 0, "malformed key, expected '=<restval>'");
|
clicon_err(OE_XML, 0, "malformed key, expected '=<restval>'");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -1697,7 +1703,7 @@ api_path2xml_vec(char **vec,
|
||||||
if ((xb = xml_new("body", x)) == NULL)
|
if ((xb = xml_new("body", x)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
xml_type_set(xb, CX_BODY);
|
xml_type_set(xb, CX_BODY);
|
||||||
if (xml_value_set(xb, restval) < 0)
|
if (restval && xml_value_set(xb, restval) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
break;
|
break;
|
||||||
case Y_LIST:
|
case Y_LIST:
|
||||||
|
|
@ -1983,3 +1989,70 @@ done:
|
||||||
return retval;
|
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
|
EOF
|
||||||
|
|
||||||
|
|
@ -96,6 +107,12 @@ expectfn "$clixon_cli -1f $clixon_cf -y /tmp/leafref.yang -l o set default-addre
|
||||||
new "cli leafref validate"
|
new "cli leafref validate"
|
||||||
expectfn "$clixon_cli -1f $clixon_cf -y /tmp/leafref.yang -l o 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"
|
new "Kill backend"
|
||||||
# Check if still alive
|
# Check if still alive
|
||||||
pid=`pgrep clixon_backend`
|
pid=`pgrep clixon_backend`
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue