* Support for YANG conditionals "must" and "when" according to RFC 7950 Sec 7.5.3 and 7.21.5

* XPATH checked at validation time
This commit is contained in:
Olof hagsand 2018-07-18 09:51:33 +02:00
parent ba7f84afee
commit 0eb9e6c8b2
14 changed files with 244 additions and 54 deletions

View file

@ -3,20 +3,22 @@
## 3.7.0 (Upcoming) ## 3.7.0 (Upcoming)
### Major changes: ### Major changes:
* Much better support for XPATH 1.0 according to https://www.w3.org/TR/xpath-10 using yacc/lex * Support for YANG conditionals "must" and "when" according to RFC 7950 Sec 7.5.3 and 7.21.5
* NOTE: Due to an error in the previous implementation, all XPATH calls on the form `x[a=str]` where `str` is a string (not a number or XML symbol), must be changed to: `x[a='str'] or x[a="str"]` * XPATH checked at validation time
* This includes all calls to `xpath_vec, xpath_first`, etc. * Support for YANG identity, identityref, must and when according to RFC 7950 Sec 7.189.
* All calls to cli_copy_config in CLI spec files must replace 2nd argument from `x[%s=%s]` to `x[%s='%s']`
* The old API is stillenabled. To define the new, define XPATH_USE_NEW in include/clixon_custom.h and recompile
* Conformance of restconf(RFC-8040) operations where prefix was used instead of module name.
* Proper specification for an operation is POST /restconf/operations/<module_name>:<rpc_procedure> HTTP/1.1
* See https://github.com/clicon/clixon/issues/31, https://github.com/clicon/clixon/pull/32 and https://github.com/clicon/clixon/issues/30
* Thanks David Cornejo and Dmitry Vakhrushev of Netgate for pointing this out.
* Support for YANG identity and identityref according to RFC 7950 Sec 7.18 and 9.10
* Previous support did no validation of values. * Previous support did no validation of values.
* Validation of types and CLI expansion * Validation of types and CLI expansion
* Example extended with inclusion of iana-if-type RFC 7224 interface identities * Example extended with inclusion of iana-if-type RFC 7224 interface identities
* Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified. * Applications which have not strictly enforced the identities may now have problems with validation and may need to be modified.
* Much improved support for XPATH 1.0 according to https://www.w3.org/TR/xpath-10 using yacc/lex
* NOTE: Due to an error in the previous implementation, all XPATH calls on the form `x[a=str]` where `str` is a string (not a number or XML symbol), must be changed to: `x[a='str'] or x[a="str"]`
* This includes all calls to `xpath_vec, xpath_first`, etc.
* All calls to cli_copy_config in CLI spec files must replace 2nd argument from `x[%s=%s]` to `x[%s='%s']`
* The old API can be enabled by setting COMPAT_XSL in include/clixon_custom.h and recompile.
* Conformance of restconf(RFC-8040) operations where prefix was used instead of module name.
* Proper specification for an operation is POST /restconf/operations/<module_name>:<rpc_procedure> HTTP/1.1
* See https://github.com/clicon/clixon/issues/31, https://github.com/clicon/clixon/pull/32 and https://github.com/clicon/clixon/issues/30
* Thanks David Cornejo and Dmitry Vakhrushev of Netgate for pointing this out.
### Minor changes: ### Minor changes:
* Added systemd example files under example/systemd * Added systemd example files under example/systemd
@ -33,7 +35,7 @@
* Added xmlns validation * Added xmlns validation
* for eg <a xmlns:x="uri"><x:b/></a> * for eg <a xmlns:x="uri"><x:b/></a>
* Added yang identityref runtime validation * Added yang identityref runtime validation
* Removed cli callback vector functions. Set COMPAT_COMPAT_CLIV if you need to keep these functions in clixon_custom.h. * Removed cli callback vector functions. Set COMPAT_CLIV if you need to keep these functions in include/clixon_custom.h.
* Replace functions as follows in CLI SPEC files: * Replace functions as follows in CLI SPEC files:
* cli_setv --> cli_set * cli_setv --> cli_set
* cli_mergev --> cli_merge * cli_mergev --> cli_merge

View file

@ -11,6 +11,7 @@ transaction support from a YANG specification.
* [Support](#support) * [Support](#support)
* [Dependencies](#dependencies) * [Dependencies](#dependencies)
* [Extending](#extending) * [Extending](#extending)
* [XML and XPATH](#xml)
* [Yang](#yang) * [Yang](#yang)
* [Netconf](#netconf) * [Netconf](#netconf)
* [Restconf](#restconf) * [Restconf](#restconf)
@ -89,9 +90,17 @@ are also available.
Plugins are written in C and easiest is to look at Plugins are written in C and easiest is to look at
[example](example/README.md) or consulting the [FAQ](doc/FAQ.md). [example](example/README.md) or consulting the [FAQ](doc/FAQ.md).
XML
===
Clixon has its own implementation of XML and XPATH implementation.
The standards covered include:
- [XML](https://www.w3.org/TR/2008/REC-xml-20081126)
- [Namespaces](https://www.w3.org/TR/2009/REC-xml-names-20091208)
- [XPATH](https://www.w3.org/TR/xpath-10)
Yang Yang
==== ====
YANG and XML is at the heart of Clixon. Yang modules are used as a YANG and XML is at the heart of Clixon. Yang modules are used as a
specification for handling XML configuration data. The YANG spec is specification for handling XML configuration data. The YANG spec is
used to generate an interactive CLI, netconf and restconf clients. It used to generate an interactive CLI, netconf and restconf clients. It
@ -100,7 +109,7 @@ also manages an XML datastore.
Clixon mainly follows [YANG 1.0 RFC 6020](https://www.rfc-editor.org/rfc/rfc6020.txt) with some exceptions: Clixon mainly follows [YANG 1.0 RFC 6020](https://www.rfc-editor.org/rfc/rfc6020.txt) with some exceptions:
- conformance: feature, if-feature, deviation - conformance: feature, if-feature, deviation
- list features: min/max-elements, unique - list features: min/max-elements, unique
- when, must, action statements - action statements
- notifications - notifications
The aim is also to cover new features in YANG 1.1 [YANG RFC 7950](https://www.rfc-editor.org/rfc/rfc7950.txt) The aim is also to cover new features in YANG 1.1 [YANG RFC 7950](https://www.rfc-editor.org/rfc/rfc7950.txt)

View file

@ -986,10 +986,10 @@ nacm_access(clicon_handle h,
goto step10; goto step10;
/* User's group */ /* User's group */
if (xpath_vec(xacm, if (xpath_vec(xacm,
#ifdef XPATH_USE_NEW #ifdef COMPAT_XSL
"groups/group[user-name='%s']",
#else
"groups/group[user-name=%s]", "groups/group[user-name=%s]",
#else
"groups/group[user-name='%s']",
#endif #endif
&gvec, &glen, username) < 0) &gvec, &glen, username) < 0)
goto done; goto done;
@ -1009,10 +1009,10 @@ nacm_access(clicon_handle h,
char *gname; char *gname;
gname = xml_find_body(gvec[j], "name"); gname = xml_find_body(gvec[j], "name");
if (xpath_first(xrlist, if (xpath_first(xrlist,
#ifdef XPATH_USE_NEW #ifdef COMPAT_XSL
".[group='%s']",
#else
".[group=%s]", ".[group=%s]",
#else
".[group='%s']",
#endif #endif
gname)!=NULL) gname)!=NULL)
break; /* found */ break; /* found */

View file

@ -1249,7 +1249,7 @@ cli_copy_config(clicon_handle h,
for (i=0; i<strlen(xpath); i++){ for (i=0; i<strlen(xpath); i++){
if (xpath[i] == '%') if (xpath[i] == '%')
j++; j++;
#ifndef XPATH_USE_NEW #ifdef COMPAT_XSL
/* This is a horrible kludge due to: /* This is a horrible kludge due to:
* (1) old xpath implementation wrongly did: a[b=x] instead of a[b='x'] * (1) old xpath implementation wrongly did: a[b=x] instead of a[b='x']
* (2) cli_copy_config has as 2nd argument such an xpath provided by user. * (2) cli_copy_config has as 2nd argument such an xpath provided by user.

View file

@ -68,10 +68,10 @@ mycallback(clicon_handle h, cvec *cvv, cvec *argv)
/* Show eth0 interfaces config using XPATH */ /* Show eth0 interfaces config using XPATH */
if (clicon_rpc_get_config(h, "running", if (clicon_rpc_get_config(h, "running",
#ifdef XPATH_USE_NEW #ifdef COMPAT_XSL
"/interfaces/interface[name='eth0']",
#else
"/interfaces/interface[name=eth0]", "/interfaces/interface[name=eth0]",
#else
"/interfaces/interface[name='eth0']",
#endif #endif
&xret) < 0) &xret) < 0)
goto done; goto done;

View file

@ -56,7 +56,13 @@ int strverscmp (__const char *__s1, __const char *__s2);
*/ */
#define XMLNS_YANG_ONLY 1 #define XMLNS_YANG_ONLY 1
/* Set if you want all old xpath functions in clixon_xsl.* to use the new /* Set if you want to enable old xpath functions in clixon_xsl.* instead of the
* xpath functions in clixon_xpath.* * the new xpath functions in clixon_xpath.*
*/ * Note that when changing from old xpath code to new, calls on the form
#undef XPATH_USE_NEW * `x[a=str]` where `str` is a string (not a number or XML symbol),
* must be changed to: `x[a='str'] or x[a="str"]`
* Enabling COMPAT_XSL may make sense if you have written a lot of user code that
* relieson the error above. Or if a bug appears in the newimplementation.
* @see test/lib.sh
*/
#undef COMPAT_XSL

View file

@ -101,14 +101,14 @@ int xpath_vec_bool(cxobj *xcur, char *format, ...);
int xpath_vec_ctx(cxobj *xcur, char *xpath, xp_ctx **xrp); int xpath_vec_ctx(cxobj *xcur, char *xpath, xp_ctx **xrp);
/* backward compatible */ /* backward compatible */
#ifdef XPATH_USE_NEW #ifdef COMPAT_XSL
#define xpath_first(cxtop, format, args...) xpath_first_nodeset(cxtop, format, ##args)
#define xpath_vec(cxtop, format, vec, veclen, args...) xpath_vec_nodeset(cxtop, format, vec, veclen, ##args)
#define xpath_vec_flag(cxtop, format, flags, vec, veclen, args...) xpath_vec_nodeset_flag(cxtop, format, flags, vec, veclen, ##args)
#else
#define xpath_first(cxtop, format, args...) xpath_first_xsl(cxtop, format, ##args) #define xpath_first(cxtop, format, args...) xpath_first_xsl(cxtop, format, ##args)
#define xpath_vec(cxtop, format, vec, veclen, args...) xpath_vec_xsl(cxtop, format, vec, veclen, ##args) #define xpath_vec(cxtop, format, vec, veclen, args...) xpath_vec_xsl(cxtop, format, vec, veclen, ##args)
#define xpath_vec_flag(cxtop, format, flags, vec, veclen, args...) xpath_vec_flag_xsl(cxtop, format, flags, vec, veclen, ##args) #define xpath_vec_flag(cxtop, format, flags, vec, veclen, args...) xpath_vec_flag_xsl(cxtop, format, flags, vec, veclen, ##args)
#else
#define xpath_first(cxtop, format, args...) xpath_first_nodeset(cxtop, format, ##args)
#define xpath_vec(cxtop, format, vec, veclen, args...) xpath_vec_nodeset(cxtop, format, vec, veclen, ##args)
#define xpath_vec_flag(cxtop, format, flags, vec, veclen, args...) xpath_vec_nodeset_flag(cxtop, format, flags, vec, veclen, ##args)
#endif #endif
#endif /* _CLIXON_XPATH_H */ #endif /* _CLIXON_XPATH_H */

View file

@ -428,7 +428,9 @@ xml_yang_validate_all(cxobj *xt,
int retval = -1; int retval = -1;
yang_stmt *ys; /* yang node */ yang_stmt *ys; /* yang node */
yang_stmt *yc; /* yang child */ yang_stmt *yc; /* yang child */
yang_stmt *ye; /* yang must error-message */
char *xpath; char *xpath;
int b;
/* if not given by argument (overide) use default link /* if not given by argument (overide) use default link
and !Node has a config sub-statement and it is false */ and !Node has a config sub-statement and it is false */
@ -453,17 +455,34 @@ xml_yang_validate_all(cxobj *xt,
} }
} }
break; break;
case Y_MUST: /* RFC 7950 Sec 7.5.3 */
break;
default: default:
break; break;
} }
/* "when" sub-node RFC 7950 Sec 7.21.5 */ /* must sub-node RFC 7950 Sec 7.5.3. Can be several. */
yc = NULL;
while ((yc = yn_each((yang_node*)ys, yc)) != NULL) {
if (yc->ys_keyword != Y_MUST)
continue;
xpath = yc->ys_argument; /* "must" has xpath argument */
if ((b = xpath_vec_bool(xt, "%s", xpath)) < 0)
goto done;
if (!b){
if ((ye = yang_find((yang_node*)yc, Y_ERROR_MESSAGE, NULL)) != NULL)
clicon_err(OE_DB, 0, "%s", ye->ys_argument);
else
clicon_err(OE_DB, 0, "xpath %s validation failed", xml_name(xt));
goto done;
}
}
/* "when" sub-node RFC 7950 Sec 7.21.5. Can only be one. */
if ((yc = yang_find((yang_node*)ys, Y_WHEN, NULL)) != NULL){ if ((yc = yang_find((yang_node*)ys, Y_WHEN, NULL)) != NULL){
xpath = yc->ys_argument; /* "when" has xpath argument */ xpath = yc->ys_argument; /* "when" has xpath argument */
if (xpath_first(xt, "%s", xpath)) if ((b = xpath_vec_bool(xt, "%s", xpath)) < 0)
; goto done;
fprintf(stderr, "%s %s\n", __FUNCTION__, xpath); if (!b){
clicon_err(OE_DB, 0, "xpath %s validation failed", xml_name(xt));
goto done;
}
} }
} }
retval = 0; retval = 0;
@ -1041,10 +1060,10 @@ api_path_fmt2xpath(char *api_path_fmt,
goto done; goto done;
} }
cprintf(cb, cprintf(cb,
#ifdef XPATH_USE_NEW #ifdef COMPAT_XSL
"[%s='%s']",
#else
"[%s=%s]", "[%s=%s]",
#else
"[%s='%s']",
#endif #endif
cv_name_get(cv), str); cv_name_get(cv), str);
free(str); free(str);
@ -1464,10 +1483,10 @@ api_path2xpath_cvv(yang_spec *yspec,
v = val; v = val;
while ((cvi = cvec_each(cvk, cvi)) != NULL){ while ((cvi = cvec_each(cvk, cvi)) != NULL){
cprintf(xpath, cprintf(xpath,
#ifdef XPATH_USE_NEW #ifdef COMPAT_XSL
"[%s='%s']",
#else
"[%s=%s]", "[%s=%s]",
#else
"[%s='%s']",
#endif #endif
cv_string_get(cvi), v); cv_string_get(cvi), v);
v += strlen(v)+1; v += strlen(v)+1;

View file

@ -776,6 +776,9 @@ xp_relop(xp_ctx *xc1,
} /* switch type */ } /* switch type */
} }
ok: ok:
/* Just ensure bool is 0 or 1 */
if (xr->xc_type == XT_BOOL && xr->xc_bool != 0)
xr->xc_bool = 1;
*xrp = xr; *xrp = xr;
retval = 0; retval = 0;
done: done:
@ -849,7 +852,6 @@ xp_eval(xp_ctx *xc,
xp_ctx *xr2 = NULL; xp_ctx *xr2 = NULL;
int use_xr0 = 0; /* In 2nd child use transitively result of 1st child */ int use_xr0 = 0; /* In 2nd child use transitively result of 1st child */
assert(xc->xc_initial);
if (debug){ if (debug){
cbuf *cb; cbuf *cb;
if ((cb = cbuf_new()) == NULL){ if ((cb = cbuf_new()) == NULL){

View file

@ -5,8 +5,9 @@
testnr=0 testnr=0
testname= testname=
# Set to 1 if new xpath. Set to nothing, or comment if old # Set to 1 to enable old XSL implementation. Set to nothing, or comment if new.
#XPATH_USE_NEW=1 # @see include/clixon_custom.h
#COMPAT_XSL=1
# For memcheck # For memcheck
#clixon_cli="valgrind --leak-check=full --show-leak-kinds=all clixon_cli" #clixon_cli="valgrind --leak-check=full --show-leak-kinds=all clixon_cli"

View file

@ -94,11 +94,11 @@ new "Add subtree eth/0/0 using none and create which should add eth/0/0"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><edit-config><target><candidate/></target><config><interfaces><interface operation="create"><name>eth/0/0</name><type>ex:eth</type></interface></interfaces></config><default-operation>none</default-operation> </edit-config></rpc>]]>]]>' "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# Too many quotes, (single inside double inside single) need to fool bash # Too many quotes, (single inside double inside single) need to fool bash
if [ -n "$XPATH_USE_NEW" ]; then if [ -z "$COMPAT_XSL" ]; then
cat <<EOF > $tmp # new cat <<EOF > $tmp # new
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth/0/0']"/></get-config></rpc>]]>]]> <rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth/0/0']"/></get-config></rpc>]]>]]>
EOF EOF
else else # old
cat <<EOF > $tmp cat <<EOF > $tmp
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth/0/0]"/></get-config></rpc>]]>]]> <rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth/0/0]"/></get-config></rpc>]]>]]>
EOF EOF
@ -122,12 +122,12 @@ new "netconf edit config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interfaces><interface><name>eth/0/0</name></interface><interface><name>eth1</name><enabled>true</enabled><ipv4><address><ip>9.2.3.4</ip><prefix-length>24</prefix-length></address></ipv4></interface></interfaces></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
# Too many quotes # Too many quotes
if [ -n "$XPATH_USE_NEW" ]; then if [ -z "$COMPAT_XSL" ]; then
cat <<EOF > $tmp # new cat <<EOF > $tmp # new
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth1']/enabled"/></get-config></rpc>]]>]]> <rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth1']/enabled"/></get-config></rpc>]]>]]>
EOF EOF
else else
cat <<EOF > $tmp # new cat <<EOF > $tmp # old
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth1]/enabled"/></get-config></rpc>]]>]]> <rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name=eth1]/enabled"/></get-config></rpc>]]>]]>
EOF EOF
fi fi
@ -136,7 +136,7 @@ new "netconf get config xpath"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "$(cat $tmp)" "^<rpc-reply><data><interfaces><interface><name>eth1</name><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "$(cat $tmp)" "^<rpc-reply><data><interfaces><interface><name>eth1</name><enabled>true</enabled></interface></interfaces></data></rpc-reply>]]>]]>$"
# Too many quotes # Too many quotes
if [ -n "$XPATH_USE_NEW" ]; then if [ -z "$COMPAT_XSL" ]; then
cat <<EOF > $tmp # new cat <<EOF > $tmp # new
<rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth1']/enabled/../.."/></get-config></rpc>]]>]]> <rpc><get-config><source><candidate/></source><filter type="xpath" select="/interfaces/interface[name='eth1']/enabled/../.."/></get-config></rpc>]]>]]>
EOF EOF

View file

@ -121,7 +121,7 @@ fi
new "verify running from start, should be: l,c,y0,y1,y2,y3; y1 and y3 sorted. Note this fails if XML_SORT set to false" new "verify running from start, should be: l,c,y0,y1,y2,y3; y1 and y3 sorted. Note this fails if XML_SORT set to false"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><c><d>hej</d></c><l>hopp</l><y0>d</y0><y0>b</y0><y0>c</y0><y0>a</y0><y1>a</y1><y1>b</y1><y1>c</y1><y1>d</y1><y2><k>d</k><a>bar</a></y2><y2><k>a</k><a>bar</a></y2><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>bar</a></y2><y3><k>a</k><a>bar</a></y3><y3><k>b</k><a>bar</a></y3><y3><k>c</k><a>bar</a></y3><y3><k>d</k><a>bar</a></y3></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><c><d>hej</d></c><l>hopp</l><y0>d</y0><y0>b</y0><y0>c</y0><y0>a</y0><y1>a</y1><y1>b</y1><y1>c</y1><y1>d</y1><y2><k>d</k><a>bar</a></y2><y2><k>a</k><a>bar</a></y2><y2><k>c</k><a>bar</a></y2><y2><k>b</k><a>bar</a></y2><y3><k>a</k><a>bar</a></y3><y3><k>b</k><a>bar</a></y3><y3><k>c</k><a>bar</a></y3><y3><k>d</k><a>bar</a></y3></data></rpc-reply>]]>]]>$"
if [ -n "$XPATH_USE_NEW" ]; then #new if [ -z "$COMPAT_XSL" ]; then #new
new "get each ordered-by user leaf-list" new "get each ordered-by user leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k='a']\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>a</k><a>bar</a></y2></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><running/></source><filter type=\"xpath\" select=\"/y2[k='a']\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><y2><k>a</k><a>bar</a></y2></data></rpc-reply>]]>]]>$"

151
test/test_when_must.sh Executable file
View file

@ -0,0 +1,151 @@
#!/bin/bash
# Yang when and must conditional xpath specification
# Testing of validation phase.
APPNAME=example
# include err() and new() functions and creates $dir
. ./lib.sh
cfg=$dir/conf_yang.xml
fyang=$dir/test.yang
cat <<EOF > $cfg
<config>
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
<CLICON_YANG_DIR>/usr/local/share/$APPNAME/yang</CLICON_YANG_DIR>
<CLICON_YANG_MODULE_MAIN>$APPNAME</CLICON_YANG_MODULE_MAIN>
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
<CLICON_CLI_GENMODEL_COMPLETION>1</CLICON_CLI_GENMODEL_COMPLETION>
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
</config>
EOF
cat <<EOF > $fyang
module $APPNAME{
prefix ex;
identity routing-protocol {
description
"Base identity from which routing protocol identities are
derived.";
}
identity direct {
base routing-protocol;
description
"Routing pseudo-protocol which provides routes to directly
connected networks.";
}
identity static {
base routing-protocol;
description
"Static routing pseudo-protocol.";
}
list whenex {
key "type name";
leaf type {
type identityref {
base routing-protocol;
}
}
leaf name {
type string;
}
leaf route-preference {
type uint32;
}
container static-routes {
when "../type='static'" {
description
"This container is only valid for the 'static'
routing protocol.";
}
presence true;
}
}
container interface {
leaf ifType {
type enumeration {
enum ethernet;
enum atm;
}
}
leaf ifMTU {
type uint32;
}
must 'ifType != "ethernet" or ifMTU = 1500' {
error-message "An Ethernet MTU must be 1500";
}
must 'ifType != "atm" or'
+ ' (ifMTU <= 17966 and ifMTU >= 64)' {
error-message "An ATM MTU must be 64 .. 17966";
}
}
}
EOF
# kill old backend (if any)
new "kill old backend"
sudo clixon_backend -zf $cfg -y $fyang
if [ $? -ne 0 ]; then
err
fi
new "start backend -s init -f $cfg -y $fyang"
# start new backend
sudo clixon_backend -s init -f $cfg -y $fyang
if [ $? -ne 0 ]; then
err
fi
new "when: add static route"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><whenex><type>static</type><name>r1</name><static-routes/></whenex></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "when: validate ok"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "when: add direct route"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><whenex><type>direct</type><name>r2</name><static-routes/></whenex></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "when get config"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" "^<rpc-reply><data><whenex><type>direct</type><name>r2</name><static-routes/></whenex><whenex><type>static</type><name>r1</name><static-routes/></whenex></data></rpc-reply>]]>]]>$"
new "when: validate fail"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>xpath static-routes validation failed</error-message></rpc-error></rpc-reply>]]>]]>$"
new "when: discard-changes"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "must: add interface"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interface><ifType>ethernet</ifType><ifMTU>1500</ifMTU></interface></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "must: validate ok"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "must: add atm interface"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interface><ifType>atm</ifType><ifMTU>32</ifMTU></interface></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "must: atm validate fail"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>An ATM MTU must be 64 .. 17966</error-message></rpc-error></rpc-reply>]]>]]>$"
new "must: add eth interface"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><interface><ifType>ethernet</ifType><ifMTU>989</ifMTU></interface></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
new "must: eth validate fail"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error><error-tag>operation-failed</error-tag><error-type>application</error-type><error-severity>error</error-severity><error-message>An Ethernet MTU must be 1500</error-message></rpc-error></rpc-reply>]]>]]>"
# Check if still alive
pid=`pgrep clixon_backend`
if [ -z "$pid" ]; then
err "backend already dead"
fi
# kill backend
sudo clixon_backend -zf $cfg
if [ $? -ne 0 ]; then
err "kill backend"
fi
rm -rf $dir

View file

@ -136,7 +136,7 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><can
new "netconf get leaf-list" new "netconf get leaf-list"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f/e\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f/e\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
if [ -n "$XPATH_USE_NEW" ]; then # new if [ -z "$COMPAT_XSL" ]; then # new
new "netconf get leaf-list path" new "netconf get leaf-list path"
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e='hej']\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$" expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get-config><source><candidate/></source><filter type=\"xpath\" select=\"/x/f[e='hej']\"/></get-config></rpc>]]>]]>" "^<rpc-reply><data><x><f><e>hej</e><e>hopp</e></f></x></data></rpc-reply>]]>]]>$"
else # old else # old