* Limited support of RFC 7895 YANG Module Library to list modules:
* That is, limited support of: ietf-yang-library.yang * For example: `<module><name>example</name><revision/></module><module><name>ietf-restconf-monitoring</name><revision>2017-01-26</revision></module>...` * Comply to RFC 8040 3.5.3.1 rule: api-identifier = [module-name ":"] identifier * The "module-name" was a no-op before. * This means that there was no difference between eg: GET /restconf/data/ietf-yang-library:modules-state and GET /restconf/data/XXXX:modules-state
This commit is contained in:
parent
0631be19cb
commit
74fc0800ae
18 changed files with 921 additions and 120 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
|
@ -5,14 +5,23 @@
|
|||
### Major New features
|
||||
|
||||
### API changes on existing features (you may need to change your code)
|
||||
* Notification event streams enhancements
|
||||
* Limited support of RFC 7895 YANG Module Library to list modules:
|
||||
* That is, limited support of: ietf-yang-library.yang
|
||||
* For example: `<module><name>example</name><revision/></module><module><name>ietf-restconf-monitoring</name><revision>2017-01-26</revision></module>...`
|
||||
* Notification event stream enhancements
|
||||
* Yang 1.1 notification support
|
||||
* Event stream discovery support according to RFC 5277 Sec 3.2.5.1 (netconf) and RFC 8040 (restconf)
|
||||
* Event stream discovery support according to RFC 5277 Sec 3.2.5.1
|
||||
* That is, support of ietf-restconf-monitoring.yang (mimics schema in 3.2.5.1)
|
||||
* Event stream discovery support according to RFC 8040 (restconf)
|
||||
* That is, support of ietf-netconf-notification.yang
|
||||
* clixon_restconf and clixon_netconf now take -D <level> as command-line option instead of just -D
|
||||
* This aligns to clixon_cli and clixon_backend
|
||||
* Application command option -S to clixon_netconf is obsolete. Use `clixon_netconf -l s` instead.
|
||||
|
||||
### Minor changes
|
||||
* Comply to RFC 8040 3.5.3.1 rule: api-identifier = [module-name ":"] identifier
|
||||
* The "module-name" was a no-op before.
|
||||
* This means that there was no difference between eg: GET /restconf/data/ietf-yang-library:modules-state and GET /restconf/data/XXXX:modules-state
|
||||
* Unified log handling for all clicon applications using -l e|o|s|f<file>.
|
||||
* The options stand for e:stderr, o:stdout, s: syslog, f:file
|
||||
* Added file logging (`-l f` or `-l f<file>`) for cases where neither syslog nor stderr is useful.
|
||||
|
|
|
|||
|
|
@ -261,6 +261,11 @@ from_client_get_config(clicon_handle h,
|
|||
return retval;
|
||||
}
|
||||
|
||||
/*! Get streams state according to RFC 5277 and RCC 8040
|
||||
* @retval -1 Error (fatal)
|
||||
* @retval 0 OK
|
||||
* @retval 1 Statedata callback failed
|
||||
*/
|
||||
static int
|
||||
client_get_streams(clicon_handle h,
|
||||
char *xpath,
|
||||
|
|
@ -289,9 +294,18 @@ client_get_streams(clicon_handle h,
|
|||
if (stream_get_xml(h, cb) < 0)
|
||||
goto done;
|
||||
cprintf(cb,"</restconf-state>");
|
||||
/* XXX. yspec */
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &x) < 0)
|
||||
cprintf(cb,"<netconf xmlns=\"urn:ietf:params:xml:ns:netmod:notification\">");
|
||||
if (stream_get_xml(h, cb) < 0)
|
||||
goto done;
|
||||
cprintf(cb,"</netconf>");
|
||||
|
||||
/* XXX. yspec */
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &x) < 0){
|
||||
if (netconf_operation_failed_xml(xtop, "protocol", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
if (xml_merge(*xtop, x, yspec, &reason) < 0)
|
||||
goto done;
|
||||
if (reason){
|
||||
|
|
@ -299,11 +313,117 @@ client_get_streams(clicon_handle h,
|
|||
xml_purge(xc);
|
||||
if (netconf_operation_failed_xml(xtop, "rpc", reason)< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
#ifdef notyet
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (reason)
|
||||
free(reason);
|
||||
if (x)
|
||||
xml_free(x);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Get modules state according to RFC 7895
|
||||
* @retval -1 Error (fatal)
|
||||
* @retval 0 OK
|
||||
* @retval 1 Statedata callback failed
|
||||
*/
|
||||
static int
|
||||
client_get_modules(clicon_handle h,
|
||||
char *xpath,
|
||||
cxobj **xtop)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj *x = NULL;
|
||||
cxobj *xc;
|
||||
char *reason = NULL;
|
||||
yang_spec *yspec;
|
||||
cbuf *cb;
|
||||
yang_stmt *ymod = NULL;
|
||||
yang_stmt *yrev;
|
||||
|
||||
if ((yspec = clicon_dbspec_yang(h)) == NULL){
|
||||
clicon_err(OE_YANG, ENOENT, "No yang spec");
|
||||
goto done;
|
||||
}
|
||||
if (*xtop==NULL){
|
||||
clicon_err(OE_CFG, ENOENT, "XML tree expected");
|
||||
goto done;
|
||||
}
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, 0, "clicon buffer");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb,"<modules-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-yang-library\">");
|
||||
cprintf(cb,"<module-set-id>1</module-set-id>"); /* NYI */
|
||||
|
||||
while ((ymod = yn_each((yang_node*)yspec, ymod)) != NULL) {
|
||||
cprintf(cb,"<module>");
|
||||
cprintf(cb,"<name>%s</name>", ymod->ys_argument);
|
||||
if ((yrev = yang_find((yang_node*)ymod, Y_REVISION, NULL)) != NULL)
|
||||
cprintf(cb,"<revision>%s</revision>", yrev->ys_argument);
|
||||
else
|
||||
cprintf(cb,"<revision></revision>");
|
||||
cprintf(cb,"</module>");
|
||||
}
|
||||
cprintf(cb,"</modules-state>");
|
||||
|
||||
/* XXX. yspec */
|
||||
if (xml_parse_string(cbuf_get(cb), NULL, &x) < 0){
|
||||
if (netconf_operation_failed_xml(xtop, "protocol", clicon_err_reason)< 0)
|
||||
goto done;
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
if (xml_merge(*xtop, x, yspec, &reason) < 0)
|
||||
goto done;
|
||||
if (reason){
|
||||
while ((xc = xml_child_i(*xtop, 0)) != NULL)
|
||||
xml_purge(xc);
|
||||
if (netconf_operation_failed_xml(xtop, "rpc", reason)< 0)
|
||||
goto done;
|
||||
retval = 1;
|
||||
goto done;
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (reason)
|
||||
free(reason);
|
||||
if (x)
|
||||
xml_free(x);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/*! Get system state-data, including streams and plugins
|
||||
* @retval -1 Error (fatal)
|
||||
* @retval 0 OK
|
||||
* @retval 1 Statedata callback failed
|
||||
*/
|
||||
static int
|
||||
client_statedata(clicon_handle h,
|
||||
char *xpath,
|
||||
cxobj **xret)
|
||||
{
|
||||
int retval = -1;
|
||||
cxobj **xvec = NULL;
|
||||
size_t xlen;
|
||||
int i;
|
||||
|
||||
if ((retval = client_get_streams(h, xpath, xret)) != 0)
|
||||
goto done;
|
||||
if ((retval = client_get_modules(h, xpath, xret)) != 0)
|
||||
goto done;
|
||||
if ((retval = clixon_plugin_statedata(h, xpath, xret)) != 0)
|
||||
goto done;
|
||||
#if 1
|
||||
/* Code complex to filter out anything that is outside of xpath */
|
||||
if (xpath_vec(*xtop, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||
if (xpath_vec(*xret, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||
goto done;
|
||||
|
||||
/* If vectors are specified then mark the nodes found and
|
||||
|
|
@ -315,22 +435,17 @@ client_get_streams(clicon_handle h,
|
|||
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
||||
}
|
||||
/* Remove everything that is not marked */
|
||||
if (!xml_flag(*xtop, XML_FLAG_MARK))
|
||||
if (xml_tree_prune_flagged_sub(*xtop, XML_FLAG_MARK, 1, NULL) < 0)
|
||||
if (!xml_flag(*xret, XML_FLAG_MARK))
|
||||
if (xml_tree_prune_flagged_sub(*xret, XML_FLAG_MARK, 1, NULL) < 0)
|
||||
goto done;
|
||||
/* reset flag */
|
||||
if (xml_apply(*xtop, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||
if (xml_apply(*xret, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
#endif
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
if (reason)
|
||||
free(reason);
|
||||
if (x)
|
||||
xml_free(x);
|
||||
if (xvec)
|
||||
free(xvec);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -348,29 +463,24 @@ from_client_get(clicon_handle h,
|
|||
{
|
||||
int retval = -1;
|
||||
cxobj *xfilter;
|
||||
char *selector = "/";
|
||||
char *xpath = "/";
|
||||
cxobj *xret = NULL;
|
||||
int ret;
|
||||
cbuf *cbx = NULL; /* Assist cbuf */
|
||||
|
||||
if ((xfilter = xml_find(xe, "filter")) != NULL)
|
||||
if ((selector = xml_find_value(xfilter, "select"))==NULL)
|
||||
selector="/";
|
||||
if ((xpath = xml_find_value(xfilter, "select"))==NULL)
|
||||
xpath="/";
|
||||
/* Get config */
|
||||
if (xmldb_get(h, "running", selector, 0, &xret) < 0){
|
||||
if (xmldb_get(h, "running", xpath, 0, &xret) < 0){
|
||||
if (netconf_operation_failed(cbret, "application", "read registry")< 0)
|
||||
goto done;
|
||||
goto ok;
|
||||
}
|
||||
/* Get state data from plugins as defined by plugin_statedata(), if any */
|
||||
assert(xret);
|
||||
|
||||
#if 1 /* get netconf state data */
|
||||
if ((ret = client_get_streams(h, selector, &xret)) < 0)
|
||||
goto done;
|
||||
#endif
|
||||
clicon_err_reset();
|
||||
if ((ret = clixon_plugin_statedata(h, selector, &xret)) < 0)
|
||||
if ((ret = client_statedata(h, xpath, &xret)) < 0)
|
||||
goto done;
|
||||
if (ret == 0){ /* OK */
|
||||
cprintf(cbret, "<rpc-reply>");
|
||||
|
|
|
|||
|
|
@ -775,6 +775,10 @@ main(int argc,
|
|||
goto done;
|
||||
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-restconf-monitoring", NULL)< 0)
|
||||
goto done;
|
||||
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-netconf-notification", NULL)< 0)
|
||||
goto done;
|
||||
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-yang-library", NULL)< 0)
|
||||
goto done;
|
||||
/* Set options: database dir and yangspec (could be hidden in connect?)*/
|
||||
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -125,11 +125,8 @@ clixon_plugin_statedata(clicon_handle h,
|
|||
cxobj **xtop)
|
||||
{
|
||||
int retval = -1;
|
||||
int i;
|
||||
cxobj *x = NULL;
|
||||
yang_spec *yspec;
|
||||
cxobj **xvec = NULL;
|
||||
size_t xlen;
|
||||
cxobj *xc;
|
||||
clixon_plugin *cp = NULL;
|
||||
plgstatedata_t *fn; /* Plugin statedata fn */
|
||||
|
|
@ -168,25 +165,6 @@ clixon_plugin_statedata(clicon_handle h,
|
|||
x = NULL;
|
||||
}
|
||||
}
|
||||
/* Code complex to filter out anything that is outside of xpath */
|
||||
if (xpath_vec(*xtop, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
|
||||
goto done;
|
||||
|
||||
/* If vectors are specified then mark the nodes found and
|
||||
* then filter out everything else,
|
||||
* otherwise return complete tree.
|
||||
*/
|
||||
if (xvec != NULL){
|
||||
for (i=0; i<xlen; i++)
|
||||
xml_flag_set(xvec[i], XML_FLAG_MARK);
|
||||
}
|
||||
/* Remove everything that is not marked */
|
||||
if (!xml_flag(*xtop, XML_FLAG_MARK))
|
||||
if (xml_tree_prune_flagged_sub(*xtop, XML_FLAG_MARK, 1, NULL) < 0)
|
||||
goto done;
|
||||
/* reset flag */
|
||||
if (xml_apply(*xtop, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
|
||||
goto done;
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
@ -194,8 +172,6 @@ clixon_plugin_statedata(clicon_handle h,
|
|||
free(reason);
|
||||
if (x)
|
||||
xml_free(x);
|
||||
if (xvec)
|
||||
free(xvec);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@
|
|||
/*
|
||||
* Types
|
||||
*/
|
||||
/* subscription callback */
|
||||
typedef int (*subscription_fn_t)(clicon_handle, void *filter, void *arg);
|
||||
|
||||
/* Notification subscription info
|
||||
* @see client_subscription in config_client.h
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -68,7 +68,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 -D 1 f /usr/local/etc/example.xml" -s /bin/sh www-data
|
||||
sudo su -c "/www-data/clixon_restconf -D 1 -f /usr/local/etc/example.xml" -s /bin/sh www-data
|
||||
```
|
||||
Look at syslog:
|
||||
```
|
||||
|
|
@ -79,3 +79,13 @@ Send command:
|
|||
```
|
||||
curl -G http://127.0.0.1/restconf/data/*
|
||||
```
|
||||
|
||||
You can also run restconf in a debugger.
|
||||
```
|
||||
sudo gdb /www-data/clixon_restconf
|
||||
(gdb) run -D 1 -f /usr/local/etc/example.xml
|
||||
```
|
||||
but you need to ensure /www-data/fastcgi_restconf.sock has the following access:
|
||||
```
|
||||
rwxr-xr-x 1 www-data www-data 0 sep 22 11:46 /www-data/fastcgi_restconf.sock
|
||||
```
|
||||
|
|
@ -34,6 +34,8 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* This program should be run as user www-data
|
||||
*
|
||||
* See draft-ietf-netconf-restconf-13.txt [draft]
|
||||
|
||||
* sudo apt-get install libfcgi-dev
|
||||
|
|
@ -46,6 +48,10 @@
|
|||
* api/test
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -615,7 +621,13 @@ main(int argc,
|
|||
/* Parse yang database spec file */
|
||||
if (yang_spec_main(h) == NULL)
|
||||
goto done;
|
||||
|
||||
/* Add system modules */
|
||||
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-restconf-monitoring", NULL)< 0)
|
||||
goto done;
|
||||
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-netconf-notification", NULL)< 0)
|
||||
goto done;
|
||||
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-yang-library", NULL)< 0)
|
||||
goto done;
|
||||
/* Call start function in all plugins before we go interactive
|
||||
Pass all args after the standard options to plugin_start
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -620,33 +620,51 @@ yang_find_schemanode(yang_node *yn,
|
|||
*/
|
||||
yang_stmt *
|
||||
yang_find_topnode(yang_spec *ysp,
|
||||
char *argument,
|
||||
char *nodeid,
|
||||
yang_class class)
|
||||
{
|
||||
yang_stmt *ys = NULL;
|
||||
yang_stmt *yc = NULL;
|
||||
yang_stmt *ymod = NULL; /* module */
|
||||
yang_stmt *yres = NULL; /* result */
|
||||
char *prefix = NULL;
|
||||
char *id = NULL;
|
||||
int i;
|
||||
|
||||
if (yang_nodeid_split(nodeid, &prefix, &id) < 0)
|
||||
goto done;
|
||||
if (prefix){
|
||||
if ((ymod = yang_find((yang_node*)ysp, Y_MODULE, prefix)) != NULL){
|
||||
if ((yres = yang_find((yang_node*)ymod, 0, id)) != NULL)
|
||||
goto ok;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else /* No prefix given - loop through and find first */
|
||||
for (i=0; i<ysp->yp_len; i++){
|
||||
ys = ysp->yp_stmt[i];
|
||||
ymod = ysp->yp_stmt[i];
|
||||
switch (class){
|
||||
case YC_NONE:
|
||||
if ((yc = yang_find((yang_node*)ys, 0, argument)) != NULL)
|
||||
return yc;
|
||||
if ((yres = yang_find((yang_node*)ymod, 0, id)) != NULL)
|
||||
goto ok;
|
||||
break;
|
||||
case YC_DATANODE:
|
||||
if ((yc = yang_find_datanode((yang_node*)ys, argument)) != NULL)
|
||||
return yc;
|
||||
if ((yres = yang_find_datanode((yang_node*)ymod, id)) != NULL)
|
||||
goto ok;
|
||||
break;
|
||||
case YC_SCHEMANODE:
|
||||
if ((yc = yang_find_schemanode((yang_node*)ys, argument)) != NULL)
|
||||
return yc;
|
||||
if ((yres = yang_find_schemanode((yang_node*)ymod, id)) != NULL)
|
||||
goto ok;
|
||||
break;
|
||||
case YC_DATADEFINITION:
|
||||
break; /* nyi */
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
ok:
|
||||
done:
|
||||
if (prefix)
|
||||
free(prefix);
|
||||
if (id)
|
||||
free(id);
|
||||
return yres;
|
||||
}
|
||||
|
||||
/*! Given a yang statement, find the prefix associated to this module
|
||||
|
|
@ -822,7 +840,6 @@ yarg_prefix(yang_stmt *ys)
|
|||
return prefix;
|
||||
}
|
||||
|
||||
|
||||
/*! Split yang node identifier into prefix and identifer.
|
||||
* @param[in] node-id
|
||||
* @param[out] prefix Malloced string. May be NULL.
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ new "restconf DELETE whole datastore"
|
|||
expecteq "$(curl -u adm1:bar -sS -X DELETE http://localhost/restconf/data)" ""
|
||||
|
||||
new2 "auth get"
|
||||
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data": null}
|
||||
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data/x)" 'null
|
||||
'
|
||||
|
||||
new "auth set authentication config"
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ fyang=$dir/test.yang
|
|||
fyangerr=$dir/err.yang
|
||||
nacmfile=$dir/nacmfile
|
||||
|
||||
# Note filter out example_backend_nacm.so in CLICON_BACKEND_REGEXP below
|
||||
cat <<EOF > $cfg
|
||||
<config>
|
||||
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||
|
|
@ -190,7 +191,7 @@ new "restconf DELETE whole datastore"
|
|||
expecteq "$(curl -u adm1:bar -sS -X DELETE http://localhost/restconf/data)" ""
|
||||
|
||||
new2 "auth get"
|
||||
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||
expecteq "$(curl -u adm1:bar -sS -X GET http://localhost/restconf/data/ietf-interfaces:interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
|
||||
'
|
||||
|
||||
new "Set x to 0"
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ if [ $? -ne 0 ]; then
|
|||
err
|
||||
fi
|
||||
new "start backend -s init -f $cfg -y $fyang"
|
||||
sudo $clixon_backend -s init -f $cfg -y $fyang -D 1
|
||||
sudo $clixon_backend -s init -f $cfg -y $fyang # -D 1
|
||||
|
||||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
|
|
@ -77,26 +77,21 @@ new "kill old restconf daemon"
|
|||
sudo pkill -u www-data clixon_restconf
|
||||
|
||||
new "start restconf daemon"
|
||||
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg # -D 1
|
||||
sudo start-stop-daemon -S -q -o -b -x /www-data/clixon_restconf -d /www-data -c www-data -- -f $cfg -D 1
|
||||
|
||||
sleep 1
|
||||
|
||||
new "restconf tests"
|
||||
|
||||
# get the stream list using netconf
|
||||
new "netconf event stream discovery RFC5277 Sec 3.2.5"
|
||||
echo "$clixon_netconf -qf $cfg -y $fyang"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" selector="netconf/streams" xmlns="urn:ietf:params:xml:ns:netmod:notification"/></get></rpc>]]>]]>' '<rpc-reply><data><restconf-state><streams><stream><name>NETCONF</name><description>default NETCONF event stream</description><replay-support>false</replay-support></stream><stream><name>CLICON</name><description>Clicon logs</description><replay-support>false</replay-support></stream></streams></restconf-state></data></rpc-reply>]]>]]>'
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="netconf/streams" xmlns="urn:ietf:params:xml:ns:netmod:notification"/></get></rpc>]]>]]>' '<rpc-reply><data><netconf><streams><stream><name>NETCONF</name><description>default NETCONF event stream</description><replay-support>false</replay-support></stream><stream><name>CLICON</name><description>Clicon logs</description><replay-support>false</replay-support></stream></streams></netconf></data></rpc-reply>]]>]]>'
|
||||
|
||||
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="subtree"><netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"><streams/></netconf></filter></get></rpc>]]>]]>' '<rpc-reply><data><netconf><streams><stream><name>NETCONF</name>'
|
||||
new "netconf event stream discovery RFC8040 Sec 6.2"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="restconf-state/streams" xmlns="urn:ietf:params:xml:ns:netmod:notification"/></get></rpc>]]>]]>' '<rpc-reply><data><restconf-state><streams><stream><name>NETCONF</name><description>default NETCONF event stream</description><replay-support>false</replay-support></stream><stream><name>CLICON</name><description>Clicon logs</description><replay-support>false</replay-support></stream></streams></restconf-state></data></rpc-reply>]]>]]>'
|
||||
|
||||
#expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><get><filter type="subtree"><netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"><streams/></netconf></filter></get></rpc>]]>]]>' '<rpc-reply message-id="101" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><data><netconf xmlns="urn:ietf:params:xml:ns:netmod:notification"><streams><stream><name>NETCONF</name>'
|
||||
new "restconf event stream discovery RFC8040 Sec 6.2"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/streams" 0 '{"streams": {"stream": \[{"name": "CLICON","description": "Clicon logs","replay-support": false},{ "name": "NETCONF","description": "default NETCONF event stream","replay-support": false}\]}}'
|
||||
|
||||
# get the stream list using restconf
|
||||
new "restconf GET datastore"
|
||||
#expectfn "curl -s -X GET http://localhost/restconf/data/ietf-restconf-monitoring:restconf-state/streams" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||
|
||||
new "netconf subscription"
|
||||
#new "netconf subscription"
|
||||
#expectwait "$clixon_netconf -qf $cfg -y $fyang" "<rpc><create-subscription><stream>ROUTING</stream></create-subscription></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]><notification><event>Routing notification</event></notification>]]>]]>$" 30
|
||||
|
||||
new "Kill restconf daemon"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ APPNAME=example
|
|||
# include err() and new() functions and creates $dir
|
||||
. ./lib.sh
|
||||
|
||||
exit 0 # NYI
|
||||
|
||||
|
||||
cfg=$dir/conf_yang.xml
|
||||
fyang=$dir/test.yang
|
||||
|
|
@ -91,6 +91,8 @@ expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candid
|
|||
new "minmax: empty"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><default-operation>replace</default-operation><config><c/></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
exit # NYI
|
||||
|
||||
new "minmax: validate should fail"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><validate><source><candidate/></source></validate></rpc>]]>]]>" "^<rpc-reply><rpc-error/></rpc-reply>]]>]]>$"
|
||||
|
||||
|
|
|
|||
|
|
@ -135,6 +135,10 @@ if [ -z "$match" ]; then
|
|||
err "$expect" "$ret"
|
||||
fi
|
||||
|
||||
new "restconf schema resource, RFC 8040 sec 3.7 according to RFC 7895"
|
||||
expecteq "$(curl -s -H 'Accept: application/yang-data+json' -G http://localhost/restconf/data/ietf-yang-library:modules-state/module=ietf-routing,2014-10-26/)" '{"module": [{"name": "ietf-routing","revision": "2014-10-26"}]}
|
||||
'
|
||||
|
||||
new "restconf options. RFC 8040 4.1"
|
||||
expectfn "curl -i -s -X OPTIONS http://localhost/restconf/data" 0 "Allow: OPTIONS,HEAD,GET,POST,PUT,DELETE"
|
||||
|
||||
|
|
@ -142,16 +146,23 @@ new "restconf head. RFC 8040 4.2"
|
|||
expectfn "curl -s -I http://localhost/restconf/data" 0 "HTTP/1.1 200 OK"
|
||||
#Content-Type: application/yang-data+json"
|
||||
|
||||
new2 "restconf empty rpc"
|
||||
new "restconf empty rpc"
|
||||
expecteq "$(curl -s -X POST -d {\"input\":{\"name\":\"\"}} http://localhost/restconf/operations/example:empty)" ""
|
||||
|
||||
new2 "restconf get empty config + state json"
|
||||
expecteq "$(curl -sSG http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||
expecteq "$(curl -sSG http://localhost/restconf/data/interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
|
||||
'
|
||||
|
||||
new2 "restconf get empty config + state json with module name"
|
||||
expecteq "$(curl -sSG http://localhost/restconf/data/ietf-interfaces:interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
|
||||
'
|
||||
|
||||
new2 "restconf get empty config + state json with wrong module name"
|
||||
expecteq "$(curl -sSG http://localhost/restconf/data/badmodule:interfaces-state)" '{"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "operation-failed","error-type": "protocol","error-severity": "error","error-message": "No yang node found: badmodule:interfaces-state"}}}}
'
|
||||
|
||||
new "restconf get empty config + state xml"
|
||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data)
|
||||
expect="<data><interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state></data>"
|
||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/data/interfaces-state)
|
||||
expect="<interfaces-state><interface><name>eth0</name><type>ex:eth</type><if-index>42</if-index></interface></interfaces-state>"
|
||||
match=`echo $ret | grep -EZo "$expect"`
|
||||
if [ -z "$match" ]; then
|
||||
err "$expect" "$ret"
|
||||
|
|
@ -184,7 +195,7 @@ if [ -z "$match" ]; then
|
|||
fi
|
||||
|
||||
new2 "restconf GET datastore"
|
||||
expecteq "$(curl -s -X GET http://localhost/restconf/data)" '{"data": {"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||
expecteq "$(curl -s -X GET http://localhost/restconf/data/interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
|
||||
'
|
||||
|
||||
# Exact match
|
||||
|
|
@ -201,19 +212,23 @@ new "restconf Check interfaces eth/0/0 added"
|
|||
expectfn "curl -s -G http://localhost/restconf/data" 0 '{"interfaces": {"interface": \[{"name": "eth/0/0","type": "ex:eth","enabled": true}\]},"interfaces-state": {"interface": \[{"name": "eth0","type": "ex:eth","if-index": 42}\]}}
|
||||
'
|
||||
|
||||
new2 "restconf delete interfaces"
|
||||
new "restconf delete interfaces"
|
||||
expecteq $(curl -s -X DELETE http://localhost/restconf/data/interfaces) ""
|
||||
|
||||
new "restconf Check empty config"
|
||||
expectfn "curl -sG http://localhost/restconf/data" 0 "$state"
|
||||
expectfn "curl -sG http://localhost/restconf/data/interfaces-state" 0 "$state"
|
||||
|
||||
new "restconf Add interfaces subtree eth/0/0 using POST"
|
||||
expectfn 'curl -s -X POST -d {"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}} http://localhost/restconf/data/interfaces' 0 ""
|
||||
# XXX cant get this to work
|
||||
#expecteq "$(curl -s -X POST -d '{"interface":{"name":"eth/0/0","type\":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces)" ""
|
||||
|
||||
new2 "restconf Check eth/0/0 added"
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||
new2 "restconf Check eth/0/0 added config"
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces)" '{"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]}}
|
||||
'
|
||||
|
||||
new2 "restconf Check eth/0/0 added state"
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces-state)" '{"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}
|
||||
'
|
||||
|
||||
new2 "restconf Re-post eth/0/0 which should generate error"
|
||||
|
|
@ -226,7 +241,7 @@ new "Add nothing using POST"
|
|||
expectfn 'curl -s -X POST http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0' 0 '"ietf-restconf:errors" : {"error": {"rpc-error": {"error-tag": "malformed-message","error-type": "rpc","error-severity": "error","error-message": " on line 1: syntax error at or before:'
|
||||
|
||||
new2 "restconf Check description added"
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces)" '{"interfaces": {"interface": [{"name": "eth/0/0","description": "The-first-interface","type": "ex:eth","enabled": true}]}}
|
||||
'
|
||||
|
||||
new "restconf delete eth/0/0"
|
||||
|
|
@ -242,7 +257,7 @@ new "restconf Add subtree eth/0/0 using PUT"
|
|||
expecteq "$(curl -s -X PUT -d '{"interface":{"name":"eth/0/0","type":"ex:eth","enabled":true}}' http://localhost/restconf/data/interfaces/interface=eth%2f0%2f0)" ""
|
||||
|
||||
new2 "restconf get subtree"
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data)" '{"data": {"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]},"interfaces-state": {"interface": [{"name": "eth0","type": "ex:eth","if-index": 42}]}}}
|
||||
expecteq "$(curl -s -G http://localhost/restconf/data/interfaces)" '{"interfaces": {"interface": [{"name": "eth/0/0","type": "ex:eth","enabled": true}]}}
|
||||
'
|
||||
|
||||
new2 "restconf rpc using POST json"
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ new "restconf tests"
|
|||
new "restconf POST initial tree"
|
||||
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
|
||||
|
||||
new "restconf GET datastore"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||
new "restconf GET datastore intial"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}'
|
||||
|
||||
new "restconf GET interface"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1/interface=local0" 0 '{"interface": \[{"name": "local0","type": "regular"}\]}'
|
||||
|
|
@ -94,31 +94,31 @@ new "restconf DELETE"
|
|||
expectfn 'curl -s -X DELETE http://localhost/restconf/data/cont1' 0 ""
|
||||
|
||||
new "restconf GET null datastore"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": null}'
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 'null'
|
||||
|
||||
new "restconf POST initial tree"
|
||||
expectfn 'curl -s -X POST -d {"cont1":{"interface":{"name":"local0","type":"regular"}}} http://localhost/restconf/data' 0 ""
|
||||
|
||||
new "restconf GET initial tree"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}'
|
||||
|
||||
new "restconf DELETE whole datastore"
|
||||
expectfn 'curl -s -X DELETE http://localhost/restconf/data' 0 ""
|
||||
|
||||
new "restconf GET null datastore"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": null}'
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 'null'
|
||||
|
||||
new "restconf PUT initial datastore"
|
||||
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""
|
||||
|
||||
new "restconf GET datastore"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}}'
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "regular"}\]}}'
|
||||
|
||||
new "restconf PUT replace datastore"
|
||||
expectfn 'curl -s -X PUT -d {"data":{"cont2":{"name":"foo"}}} http://localhost/restconf/data' 0 ""
|
||||
|
||||
new "restconf GET replaced datastore"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont2": {"name": "foo"}}}'
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont2" 0 '{"cont2": {"name": "foo"}}'
|
||||
|
||||
new "restconf PUT initial datastore again"
|
||||
expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type":"regular"}}}} http://localhost/restconf/data' 0 ""
|
||||
|
|
@ -126,9 +126,8 @@ expectfn 'curl -s -X PUT -d {"data":{"cont1":{"interface":{"name":"local0","type
|
|||
new "restconf PUT change interface"
|
||||
expectfn 'curl -s -X PUT -d {"interface":{"name":"local0","type":"atm0"}} http://localhost/restconf/data/cont1/interface=local0' 0 ""
|
||||
|
||||
|
||||
new "restconf GET datastore atm"
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data" 0 '{"data": {"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}}'
|
||||
expectfn "curl -s -X GET http://localhost/restconf/data/cont1" 0 '{"cont1": {"interface": \[{"name": "local0","type": "atm0"}\]}}'
|
||||
|
||||
new "restconf PUT add interface"
|
||||
expectfn 'curl -s -X PUT -d {"interface":{"name":"TEST","type":"eth0"}} http://localhost/restconf/data/cont1/interface=TEST' 0 ""
|
||||
|
|
|
|||
|
|
@ -117,6 +117,9 @@ new "cli not defined extension"
|
|||
# This text yields an error, but the test cannot detect the error message yet
|
||||
#expectfn "$clixon_cli -1f $cfg -y $fyangerr show version" 0 "Yang error: Extension ex:not-defined not found"
|
||||
|
||||
new "netconf schema resource, RFC 7895"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 '<rpc><get><filter type="xpath" select="modules-state/module" xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library"/></get></rpc>]]>]]>' '<module><name>ietf-yang-library</name><revision>2016-06-21</revision></module>'
|
||||
|
||||
new "netconf edit config"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><edit-config><target><candidate/></target><config><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></config></edit-config></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||
|
||||
|
|
@ -140,7 +143,7 @@ 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>]]>]]>$"
|
||||
|
||||
new "netconf get (should be some)"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x></data></rpc-reply>]]>]]>$"
|
||||
expecteof "$clixon_netconf -qf $cfg -y $fyang" 0 "<rpc><get><filter type=\"xpath\" select=\"/\"/></get></rpc>]]>]]>" "^<rpc-reply><data><x><y><a>1</a><b>2</b><c>5</c><val>one</val></y><d/></x>"
|
||||
|
||||
new "cli set leaf-list"
|
||||
expectfn "$clixon_cli -1f $cfg -y $fyang set x f e foo" 0 ""
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ YANGSPECS += ietf-netconf-acm@2018-02-14.yang
|
|||
YANGSPECS += ietf-inet-types@2013-07-15.yang
|
||||
YANGSPECS += ietf-yang-types@2013-07-15.yang
|
||||
YANGSPECS += ietf-restconf-monitoring@2017-01-26.yang
|
||||
YANGSPECS += ietf-netconf-notification@2008-07-01.yang
|
||||
YANGSPECS += ietf-yang-library@2016-06-21.yang
|
||||
|
||||
APPNAME = clixon # subdir ehere these files are installed
|
||||
|
||||
|
|
|
|||
555
yang/ietf-netconf-monitoring@2010-10-04.yang
Normal file
555
yang/ietf-netconf-monitoring@2010-10-04.yang
Normal file
|
|
@ -0,0 +1,555 @@
|
|||
module ietf-netconf-monitoring {
|
||||
|
||||
namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring";
|
||||
prefix "ncm";
|
||||
|
||||
import ietf-yang-types { prefix yang; }
|
||||
import ietf-inet-types { prefix inet; }
|
||||
|
||||
organization
|
||||
"IETF NETCONF (Network Configuration) Working Group";
|
||||
|
||||
contact
|
||||
"WG Web: <http://tools.ietf.org/wg/netconf/>
|
||||
WG List: <mailto:netconf@ietf.org>
|
||||
|
||||
WG Chair: Mehmet Ersue
|
||||
<mailto:mehmet.ersue@nsn.com>
|
||||
|
||||
WG Chair: Bert Wijnen
|
||||
<mailto:bertietf@bwijnen.net>
|
||||
|
||||
Editor: Mark Scott
|
||||
<mailto:mark.scott@ericsson.com>
|
||||
|
||||
Editor: Martin Bjorklund
|
||||
<mailto:mbj@tail-f.com>";
|
||||
|
||||
description
|
||||
"NETCONF Monitoring Module.
|
||||
All elements in this module are read-only.
|
||||
|
||||
Copyright (c) 2010 IETF Trust and the persons identified as
|
||||
authors of the code. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or
|
||||
without modification, is permitted pursuant to, and subject
|
||||
to the license terms contained in, the Simplified BSD
|
||||
License set forth in Section 4.c of the IETF Trust's
|
||||
Legal Provisions Relating to IETF Documents
|
||||
(http://trustee.ietf.org/license-info).
|
||||
|
||||
This version of this YANG module is part of RFC 6022; see
|
||||
the RFC itself for full legal notices.";
|
||||
|
||||
revision 2010-10-04 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 6022: YANG Module for NETCONF Monitoring";
|
||||
}
|
||||
|
||||
typedef netconf-datastore-type {
|
||||
type enumeration {
|
||||
enum running;
|
||||
enum candidate;
|
||||
enum startup;
|
||||
}
|
||||
description
|
||||
"Enumeration of possible NETCONF datastore types.";
|
||||
reference
|
||||
"RFC 4741: NETCONF Configuration Protocol";
|
||||
}
|
||||
|
||||
identity transport {
|
||||
description
|
||||
"Base identity for NETCONF transport types.";
|
||||
}
|
||||
|
||||
identity netconf-ssh {
|
||||
base transport;
|
||||
description
|
||||
"NETCONF over Secure Shell (SSH).";
|
||||
reference
|
||||
"RFC 4742: Using the NETCONF Configuration Protocol
|
||||
over Secure SHell (SSH)";
|
||||
}
|
||||
|
||||
identity netconf-soap-over-beep {
|
||||
base transport;
|
||||
description
|
||||
"NETCONF over Simple Object Access Protocol (SOAP) over
|
||||
Blocks Extensible Exchange Protocol (BEEP).";
|
||||
reference
|
||||
"RFC 4743: Using NETCONF over the Simple Object
|
||||
Access Protocol (SOAP)";
|
||||
}
|
||||
|
||||
identity netconf-soap-over-https {
|
||||
base transport;
|
||||
description
|
||||
"NETCONF over Simple Object Access Protocol (SOAP)
|
||||
over Hypertext Transfer Protocol Secure (HTTPS).";
|
||||
reference
|
||||
"RFC 4743: Using NETCONF over the Simple Object
|
||||
Access Protocol (SOAP)";
|
||||
}
|
||||
|
||||
identity netconf-beep {
|
||||
base transport;
|
||||
description
|
||||
"NETCONF over Blocks Extensible Exchange Protocol (BEEP).";
|
||||
reference
|
||||
"RFC 4744: Using the NETCONF Protocol over the
|
||||
Blocks Extensible Exchange Protocol (BEEP)";
|
||||
}
|
||||
|
||||
identity netconf-tls {
|
||||
base transport;
|
||||
description
|
||||
"NETCONF over Transport Layer Security (TLS).";
|
||||
reference
|
||||
"RFC 5539: NETCONF over Transport Layer Security (TLS)";
|
||||
}
|
||||
|
||||
identity schema-format {
|
||||
description
|
||||
"Base identity for data model schema languages.";
|
||||
}
|
||||
|
||||
identity xsd {
|
||||
base schema-format;
|
||||
description
|
||||
"W3C XML Schema Definition.";
|
||||
reference
|
||||
"W3C REC REC-xmlschema-1-20041028:
|
||||
XML Schema Part 1: Structures";
|
||||
}
|
||||
|
||||
identity yang {
|
||||
base schema-format;
|
||||
description
|
||||
"The YANG data modeling language for NETCONF.";
|
||||
reference
|
||||
"RFC 6020: YANG - A Data Modeling Language for the
|
||||
Network Configuration Protocol (NETCONF)";
|
||||
}
|
||||
|
||||
identity yin {
|
||||
base schema-format;
|
||||
description
|
||||
"The YIN syntax for YANG.";
|
||||
reference
|
||||
"RFC 6020: YANG - A Data Modeling Language for the
|
||||
Network Configuration Protocol (NETCONF)";
|
||||
}
|
||||
|
||||
identity rng {
|
||||
base schema-format;
|
||||
description
|
||||
"Regular Language for XML Next Generation (RELAX NG).";
|
||||
reference
|
||||
"ISO/IEC 19757-2:2008: RELAX NG";
|
||||
}
|
||||
|
||||
identity rnc {
|
||||
base schema-format;
|
||||
description
|
||||
"Relax NG Compact Syntax";
|
||||
reference
|
||||
"ISO/IEC 19757-2:2008: RELAX NG";
|
||||
}
|
||||
|
||||
grouping common-counters {
|
||||
description
|
||||
"Counters that exist both per session, and also globally,
|
||||
accumulated from all sessions.";
|
||||
|
||||
leaf in-rpcs {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of correct <rpc> messages received.";
|
||||
}
|
||||
leaf in-bad-rpcs {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of messages received when an <rpc> message was expected,
|
||||
that were not correct <rpc> messages. This includes XML parse
|
||||
errors and errors on the rpc layer.";
|
||||
}
|
||||
leaf out-rpc-errors {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of <rpc-reply> messages sent that contained an
|
||||
<rpc-error> element.";
|
||||
}
|
||||
leaf out-notifications {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of <notification> messages sent.";
|
||||
}
|
||||
}
|
||||
|
||||
container netconf-state {
|
||||
config false;
|
||||
description
|
||||
"The netconf-state container is the root of the monitoring
|
||||
data model.";
|
||||
|
||||
container capabilities {
|
||||
description
|
||||
"Contains the list of NETCONF capabilities supported by the
|
||||
server.";
|
||||
|
||||
leaf-list capability {
|
||||
type inet:uri;
|
||||
description
|
||||
"List of NETCONF capabilities supported by the server.";
|
||||
}
|
||||
}
|
||||
|
||||
container datastores {
|
||||
description
|
||||
"Contains the list of NETCONF configuration datastores.";
|
||||
|
||||
list datastore {
|
||||
key name;
|
||||
description
|
||||
"List of NETCONF configuration datastores supported by
|
||||
the NETCONF server and related information.";
|
||||
|
||||
leaf name {
|
||||
type netconf-datastore-type;
|
||||
description
|
||||
"Name of the datastore associated with this list entry.";
|
||||
}
|
||||
container locks {
|
||||
presence
|
||||
"This container is present only if the datastore
|
||||
is locked.";
|
||||
description
|
||||
"The NETCONF <lock> and <partial-lock> operations allow
|
||||
a client to lock specific resources in a datastore. The
|
||||
NETCONF server will prevent changes to the locked
|
||||
resources by all sessions except the one that acquired
|
||||
the lock(s).
|
||||
|
||||
Monitoring information is provided for each datastore
|
||||
entry including details such as the session that acquired
|
||||
the lock, the type of lock (global or partial) and the
|
||||
list of locked resources. Multiple locks per datastore
|
||||
are supported.";
|
||||
|
||||
grouping lock-info {
|
||||
description
|
||||
"Lock related parameters, common to both global and
|
||||
partial locks.";
|
||||
|
||||
leaf locked-by-session {
|
||||
type uint32;
|
||||
mandatory true;
|
||||
description
|
||||
"The session ID of the session that has locked
|
||||
this resource. Both a global lock and a partial
|
||||
lock MUST contain the NETCONF session-id.
|
||||
|
||||
If the lock is held by a session that is not managed
|
||||
by the NETCONF server (e.g., a CLI session), a session
|
||||
id of 0 (zero) is reported.";
|
||||
reference
|
||||
"RFC 4741: NETCONF Configuration Protocol";
|
||||
}
|
||||
leaf locked-time {
|
||||
type yang:date-and-time;
|
||||
mandatory true;
|
||||
description
|
||||
"The date and time of when the resource was
|
||||
locked.";
|
||||
}
|
||||
}
|
||||
choice lock-type {
|
||||
description
|
||||
"Indicates if a global lock or a set of partial locks
|
||||
are set.";
|
||||
|
||||
container global-lock {
|
||||
description
|
||||
"Present if the global lock is set.";
|
||||
uses lock-info;
|
||||
}
|
||||
|
||||
list partial-lock {
|
||||
key lock-id;
|
||||
description
|
||||
"List of partial locks.";
|
||||
reference
|
||||
"RFC 5717: Partial Lock Remote Procedure Call (RPC) for
|
||||
NETCONF";
|
||||
|
||||
leaf lock-id {
|
||||
type uint32;
|
||||
description
|
||||
"This is the lock id returned in the <partial-lock>
|
||||
response.";
|
||||
}
|
||||
uses lock-info;
|
||||
leaf-list select {
|
||||
type yang:xpath1.0;
|
||||
min-elements 1;
|
||||
description
|
||||
"The xpath expression that was used to request
|
||||
the lock. The select expression indicates the
|
||||
original intended scope of the lock.";
|
||||
}
|
||||
leaf-list locked-node {
|
||||
type instance-identifier;
|
||||
description
|
||||
"The list of instance-identifiers (i.e., the
|
||||
locked nodes).
|
||||
|
||||
The scope of the partial lock is defined by the list
|
||||
of locked nodes.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
container schemas {
|
||||
description
|
||||
"Contains the list of data model schemas supported by the
|
||||
server.";
|
||||
|
||||
list schema {
|
||||
key "identifier version format";
|
||||
|
||||
description
|
||||
"List of data model schemas supported by the server.";
|
||||
|
||||
leaf identifier {
|
||||
type string;
|
||||
description
|
||||
"Identifier to uniquely reference the schema. The
|
||||
identifier is used in the <get-schema> operation and may
|
||||
be used for other purposes such as file retrieval.
|
||||
|
||||
For modeling languages that support or require a data
|
||||
model name (e.g., YANG module name) the identifier MUST
|
||||
match that name. For YANG data models, the identifier is
|
||||
the name of the module or submodule. In other cases, an
|
||||
identifier such as a filename MAY be used instead.";
|
||||
}
|
||||
leaf version {
|
||||
type string;
|
||||
description
|
||||
"Version of the schema supported. Multiple versions MAY be
|
||||
supported simultaneously by a NETCONF server. Each
|
||||
version MUST be reported individually in the schema list,
|
||||
i.e., with same identifier, possibly different location,
|
||||
but different version.
|
||||
|
||||
For YANG data models, version is the value of the most
|
||||
recent YANG 'revision' statement in the module or
|
||||
submodule, or the empty string if no 'revision' statement
|
||||
is present.";
|
||||
}
|
||||
leaf format {
|
||||
type identityref {
|
||||
base schema-format;
|
||||
}
|
||||
description
|
||||
"The data modeling language the schema is written
|
||||
in (currently xsd, yang, yin, rng, or rnc).
|
||||
For YANG data models, 'yang' format MUST be supported and
|
||||
'yin' format MAY also be provided.";
|
||||
}
|
||||
leaf namespace {
|
||||
type inet:uri;
|
||||
mandatory true;
|
||||
description
|
||||
"The XML namespace defined by the data model.
|
||||
|
||||
For YANG data models, this is the module's namespace.
|
||||
If the list entry describes a submodule, this field
|
||||
contains the namespace of the module to which the
|
||||
submodule belongs.";
|
||||
}
|
||||
leaf-list location {
|
||||
type union {
|
||||
type enumeration {
|
||||
enum "NETCONF";
|
||||
}
|
||||
type inet:uri;
|
||||
}
|
||||
description
|
||||
"One or more locations from which the schema can be
|
||||
retrieved. This list SHOULD contain at least one
|
||||
entry per schema.
|
||||
|
||||
A schema entry may be located on a remote file system
|
||||
(e.g., reference to file system for ftp retrieval) or
|
||||
retrieved directly from a server supporting the
|
||||
<get-schema> operation (denoted by the value 'NETCONF').";
|
||||
}
|
||||
}
|
||||
}
|
||||
container sessions {
|
||||
description
|
||||
"The sessions container includes session-specific data for
|
||||
NETCONF management sessions. The session list MUST include
|
||||
all currently active NETCONF sessions.";
|
||||
|
||||
list session {
|
||||
key session-id;
|
||||
description
|
||||
"All NETCONF sessions managed by the NETCONF server
|
||||
MUST be reported in this list.";
|
||||
|
||||
leaf session-id {
|
||||
type uint32 {
|
||||
range "1..max";
|
||||
}
|
||||
description
|
||||
"Unique identifier for the session. This value is the
|
||||
NETCONF session identifier, as defined in RFC 4741.";
|
||||
reference
|
||||
"RFC 4741: NETCONF Configuration Protocol";
|
||||
}
|
||||
leaf transport {
|
||||
type identityref {
|
||||
base transport;
|
||||
}
|
||||
mandatory true;
|
||||
description
|
||||
"Identifies the transport for each session, e.g.,
|
||||
'netconf-ssh', 'netconf-soap', etc.";
|
||||
}
|
||||
leaf username {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"The username is the client identity that was authenticated
|
||||
by the NETCONF transport protocol. The algorithm used to
|
||||
derive the username is NETCONF transport protocol specific
|
||||
and in addition specific to the authentication mechanism
|
||||
used by the NETCONF transport protocol.";
|
||||
}
|
||||
leaf source-host {
|
||||
type inet:host;
|
||||
description
|
||||
"Host identifier of the NETCONF client. The value
|
||||
returned is implementation specific (e.g., hostname,
|
||||
IPv4 address, IPv6 address)";
|
||||
}
|
||||
leaf login-time {
|
||||
type yang:date-and-time;
|
||||
mandatory true;
|
||||
description
|
||||
"Time at the server at which the session was established.";
|
||||
}
|
||||
uses common-counters {
|
||||
description
|
||||
"Per-session counters. Zero based with following reset
|
||||
behaviour:
|
||||
- at start of a session
|
||||
- when max value is reached";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
container statistics {
|
||||
description
|
||||
"Statistical data pertaining to the NETCONF server.";
|
||||
|
||||
leaf netconf-start-time {
|
||||
type yang:date-and-time;
|
||||
description
|
||||
"Date and time at which the management subsystem was
|
||||
started.";
|
||||
}
|
||||
leaf in-bad-hellos {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of sessions silently dropped because an
|
||||
invalid <hello> message was received. This includes <hello>
|
||||
messages with a 'session-id' attribute, bad namespace, and
|
||||
bad capability declarations.";
|
||||
}
|
||||
leaf in-sessions {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of sessions started. This counter is incremented
|
||||
when a <hello> message with a <session-id> is sent.
|
||||
|
||||
'in-sessions' - 'in-bad-hellos' =
|
||||
'number of correctly started netconf sessions'";
|
||||
}
|
||||
leaf dropped-sessions {
|
||||
type yang:zero-based-counter32;
|
||||
description
|
||||
"Number of sessions that were abnormally terminated, e.g.,
|
||||
due to idle timeout or transport close. This counter is not
|
||||
incremented when a session is properly closed by a
|
||||
<close-session> operation, or killed by a <kill-session>
|
||||
operation.";
|
||||
}
|
||||
uses common-counters {
|
||||
description
|
||||
"Global counters, accumulated from all sessions.
|
||||
Zero based with following reset behaviour:
|
||||
- re-initialization of NETCONF server
|
||||
- when max value is reached";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rpc get-schema {
|
||||
description
|
||||
"This operation is used to retrieve a schema from the
|
||||
NETCONF server.
|
||||
|
||||
Positive Response:
|
||||
The NETCONF server returns the requested schema.
|
||||
|
||||
Negative Response:
|
||||
If requested schema does not exist, the <error-tag> is
|
||||
'invalid-value'.
|
||||
|
||||
If more than one schema matches the requested parameters, the
|
||||
<error-tag> is 'operation-failed', and <error-app-tag> is
|
||||
'data-not-unique'.";
|
||||
|
||||
input {
|
||||
leaf identifier {
|
||||
type string;
|
||||
mandatory true;
|
||||
description
|
||||
"Identifier for the schema list entry.";
|
||||
}
|
||||
leaf version {
|
||||
type string;
|
||||
description
|
||||
"Version of the schema requested. If this parameter is not
|
||||
present, and more than one version of the schema exists on
|
||||
the server, a 'data-not-unique' error is returned, as
|
||||
described above.";
|
||||
}
|
||||
leaf format {
|
||||
type identityref {
|
||||
base schema-format;
|
||||
}
|
||||
description
|
||||
"The data modeling language of the schema. If this
|
||||
parameter is not present, and more than one formats of
|
||||
the schema exists on the server, a 'data-not-unique' error
|
||||
is returned, as described above.";
|
||||
}
|
||||
}
|
||||
output {
|
||||
anyxml data {
|
||||
description
|
||||
"Contains the schema content.";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
94
yang/ietf-netconf-notification@2008-07-01.yang
Normal file
94
yang/ietf-netconf-notification@2008-07-01.yang
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
module ietf-restconf-monitoring {
|
||||
namespace "urn:ietf:params:xml:ns:netconf:notification:1:0";
|
||||
prefix "rcmon";
|
||||
|
||||
import ietf-yang-types { prefix yang; }
|
||||
import ietf-inet-types { prefix inet; }
|
||||
|
||||
organization
|
||||
"IETF NETCONF (Network Configuration) Working Group";
|
||||
|
||||
description
|
||||
"Note this is a translation from RFC 5277 schema in section 4 to Yang.
|
||||
RFC 5277 is Copyright (C) The IETF Trust (2008).";
|
||||
|
||||
revision 2008-07-01 {
|
||||
description
|
||||
"Initial revision.";
|
||||
reference
|
||||
"RFC 5277: NETCONF Event Notifications.";
|
||||
}
|
||||
|
||||
container netconf {
|
||||
config false;
|
||||
description
|
||||
"Contains NETCONF protocol monitoring information.";
|
||||
|
||||
container capabilities {
|
||||
description
|
||||
"Contains a list of protocol capability URIs.";
|
||||
|
||||
leaf-list capability {
|
||||
type inet:uri;
|
||||
description
|
||||
"A RESTCONF protocol capability URI.";
|
||||
}
|
||||
}
|
||||
|
||||
container streams {
|
||||
description
|
||||
"Container representing the notification event streams
|
||||
supported by the server.";
|
||||
reference
|
||||
"RFC 5277, Section 3.4, <streams> element.";
|
||||
list stream {
|
||||
key name;
|
||||
description
|
||||
"Each entry describes an event stream supported by
|
||||
the server.";
|
||||
|
||||
leaf name {
|
||||
type string;
|
||||
description
|
||||
"The stream name.";
|
||||
reference
|
||||
"RFC 5277, Section 3.4, <name> element.";
|
||||
}
|
||||
|
||||
leaf description {
|
||||
type string;
|
||||
description
|
||||
"Description of stream content.";
|
||||
reference
|
||||
"RFC 5277, Section 3.4, <description> element.";
|
||||
}
|
||||
|
||||
leaf replay-support {
|
||||
type boolean;
|
||||
default false;
|
||||
description
|
||||
"Indicates if replay buffer is supported for this stream.
|
||||
If 'true', then the server MUST support the 'start-time'
|
||||
and 'stop-time' query parameters for this stream.";
|
||||
reference
|
||||
"RFC 5277, Section 3.4, <replaySupport> element.";
|
||||
}
|
||||
|
||||
leaf replay-log-creation-time {
|
||||
when "../replay-support" {
|
||||
description
|
||||
"Only present if notification replay is supported.";
|
||||
}
|
||||
type yang:date-and-time;
|
||||
description
|
||||
"Indicates the time the replay log for this stream
|
||||
was created.";
|
||||
reference
|
||||
"RFC 5277, Section 3.4, <replayLogCreationTime>
|
||||
element.";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue