* Restconf top-level operations GET root resource modified to comply with
RFC 8040 Sec 3.1
* non-pretty print remove all spaces, eg `{"operations":{"clixon-example:client-rpc":[null]`
* Replaced JSON `null` with `[null]` as proper empty JSON leaf/leaf-list encoding.
* [Cannot write to config using restconf example #91](https://github.com/clicon/clixon/issues/91)
* Updated restconf documentation (the example was wrong)
* [clixon-lib yang revision file name update #92](https://github.com/clicon/clixon/issues/92)
* Clixon-lib yang file had conflicting filename and internal yang revision.
* This was only detected in the use-case when a whole dir was loaded.
* Inserted sanity check in all yang parse routines.
* Committed updated clixon-lib yang file that triggered the error
This commit is contained in:
parent
a8906fd0bd
commit
6df434093e
12 changed files with 230 additions and 192 deletions
16
CHANGELOG.md
16
CHANGELOG.md
|
|
@ -1,5 +1,21 @@
|
||||||
# Clixon Changelog
|
# Clixon Changelog
|
||||||
|
|
||||||
|
## 4.2.0 (Expected: September)
|
||||||
|
|
||||||
|
### API changes on existing features (you may need to change your code)
|
||||||
|
* Restconf top-level operations GET root resource modified to comply with RFC 8040 Sec 3.1
|
||||||
|
* non-pretty print remove all spaces, eg `{"operations":{"clixon-example:client-rpc":[null]`
|
||||||
|
* Replaced JSON `null` with `[null]` as proper empty JSON leaf/leaf-list encoding.
|
||||||
|
|
||||||
|
### Corrected Bugs
|
||||||
|
* [Cannot write to config using restconf example #91](https://github.com/clicon/clixon/issues/91)
|
||||||
|
* Updated restconf documentation (the example was wrong)
|
||||||
|
* [clixon-lib yang revision file name update #92](https://github.com/clicon/clixon/issues/92)
|
||||||
|
* Clixon-lib yang file had conflicting filename and internal yang revision.
|
||||||
|
* This was only detected in the use-case when a whole dir was loaded.
|
||||||
|
* Inserted sanity check in all yang parse routines.
|
||||||
|
* Committed updated clixon-lib yang file that triggered the error
|
||||||
|
|
||||||
## 4.1.0 (18 August 2019)
|
## 4.1.0 (18 August 2019)
|
||||||
|
|
||||||
### Summary
|
### Summary
|
||||||
|
|
|
||||||
|
|
@ -23,57 +23,62 @@ Download and start nginx. For example on ubuntu:
|
||||||
|
|
||||||
Define nginx config file: /etc/nginx/sites-available/default
|
Define nginx config file: /etc/nginx/sites-available/default
|
||||||
```
|
```
|
||||||
server {
|
server {
|
||||||
...
|
...
|
||||||
location /restconf {
|
location /restconf {
|
||||||
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
|
||||||
include fastcgi_params;
|
include fastcgi_params;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Start nginx daemon
|
Start nginx daemon
|
||||||
```
|
```
|
||||||
sudo /etc/init.d nginx start
|
sudo /etc/init.d nginx start
|
||||||
```
|
```
|
||||||
Alternatively, start it via systemd:
|
Alternatively, start it via systemd:
|
||||||
```
|
```
|
||||||
sudo /etc/init.d/nginx start
|
sudo systemctl start nginx.service
|
||||||
sudo systemctl start start.service
|
```
|
||||||
|
|
||||||
|
Start clixon backend daemon (if not already started)
|
||||||
|
```
|
||||||
|
sudo clixon_backend -s init -f /usr/local/etc/example.xml
|
||||||
```
|
```
|
||||||
|
|
||||||
Start clixon restconf daemon
|
Start clixon restconf daemon
|
||||||
```
|
```
|
||||||
> sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data
|
|
||||||
|
sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data
|
||||||
```
|
```
|
||||||
|
|
||||||
Make restconf calls with curl
|
Make restconf calls with curl (or other http client). Example of writing a new interface specification:
|
||||||
```
|
```
|
||||||
> curl -G http://127.0.0.1/restconf/data/ietf-interfaces:interfaces
|
curl -sX PUT http://localhost/restconf/data/ietf-interfaces:interfaces -H 'Content-Type: application/yang-data+json' -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth1","type":"clixon-example:eth","enabled":true}}}'
|
||||||
[
|
```
|
||||||
|
|
||||||
|
Get the data
|
||||||
|
```
|
||||||
|
curl -X GET http://127.0.0.1/restconf/data/ietf-interfaces:interfaces
|
||||||
{
|
{
|
||||||
"ietf-interfaces:interfaces": {
|
"ietf-interfaces:interfaces": {
|
||||||
"interface":[
|
"interface": [
|
||||||
{
|
{
|
||||||
"name": "eth9",
|
"name": "eth1",
|
||||||
"type": "ex:eth",
|
"type": "clixon-example:eth",
|
||||||
"enabled": true,
|
"enabled": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
|
||||||
```
|
```
|
||||||
Get the type of a specific interface:
|
Get the type of a specific interface:
|
||||||
```
|
```
|
||||||
> curl -G http://127.0.0.1/restconf/data/interfaces/interface=eth9/type
|
curl -X GET http://127.0.0.1/restconf/data/ietf-interfacesinterfaces/interface=eth1/type
|
||||||
{
|
{
|
||||||
"ietf-interfaces:type": "eth"
|
"ietf-interfaces:type": "clixon-example:eth"
|
||||||
}
|
}
|
||||||
```
|
|
||||||
Example of writing a new interfaces specification:
|
|
||||||
```
|
|
||||||
curl -sX PUT http://localhost/restconf/data -d '{"ietf-interfaces:interfaces":{"interface":{"name":"eth1","type":"ex:eth","enabled":true}}}'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Streams
|
## Streams
|
||||||
|
|
@ -83,7 +88,7 @@ RFC8040 Section 6 using SSE. One native and one using Nginx
|
||||||
nchan. The Nchan alternaitve is described in the
|
nchan. The Nchan alternaitve is described in the
|
||||||
next section.
|
next section.
|
||||||
|
|
||||||
The (example)[../../example/README.md] creates an EXAMPLE stream.
|
The [example](../../example/main/README.md) creates an EXAMPLE stream.
|
||||||
|
|
||||||
Set the Clixon configuration options:
|
Set the Clixon configuration options:
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -449,7 +449,10 @@ api_operations_get(clicon_handle h,
|
||||||
cprintf(cbx, "<operations>");
|
cprintf(cbx, "<operations>");
|
||||||
break;
|
break;
|
||||||
case YANG_DATA_JSON:
|
case YANG_DATA_JSON:
|
||||||
cprintf(cbx, "{\"operations\": {");
|
if (pretty)
|
||||||
|
cprintf(cbx, "{\"operations\": {\n");
|
||||||
|
else
|
||||||
|
cprintf(cbx, "{\"operations\":{");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
@ -467,14 +470,19 @@ api_operations_get(clicon_handle h,
|
||||||
cprintf(cbx, "<%s xmlns=\"%s\"/>", yang_argument_get(yc), namespace);
|
cprintf(cbx, "<%s xmlns=\"%s\"/>", yang_argument_get(yc), namespace);
|
||||||
break;
|
break;
|
||||||
case YANG_DATA_JSON:
|
case YANG_DATA_JSON:
|
||||||
if (i++)
|
if (i++){
|
||||||
cprintf(cbx, ",");
|
cprintf(cbx, ",");
|
||||||
cprintf(cbx, "\"%s:%s\": null", yang_argument_get(ymod), yang_argument_get(yc));
|
if (pretty)
|
||||||
|
cprintf(cbx, "\n\t");
|
||||||
|
}
|
||||||
|
if (pretty)
|
||||||
|
cprintf(cbx, "\"%s:%s\": [null]", yang_argument_get(ymod), yang_argument_get(yc));
|
||||||
|
else
|
||||||
|
cprintf(cbx, "\"%s:%s\":[null]", yang_argument_get(ymod), yang_argument_get(yc));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (media_out){
|
switch (media_out){
|
||||||
|
|
@ -482,7 +490,10 @@ api_operations_get(clicon_handle h,
|
||||||
cprintf(cbx, "</operations>");
|
cprintf(cbx, "</operations>");
|
||||||
break;
|
break;
|
||||||
case YANG_DATA_JSON:
|
case YANG_DATA_JSON:
|
||||||
cprintf(cbx, "}}");
|
if (pretty)
|
||||||
|
cprintf(cbx, "}\n}");
|
||||||
|
else
|
||||||
|
cprintf(cbx, "}}");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
4
configure
vendored
4
configure
vendored
|
|
@ -2172,9 +2172,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||||
: ${INSTALLFLAGS="-s"}
|
: ${INSTALLFLAGS="-s"}
|
||||||
|
|
||||||
CLIXON_VERSION_MAJOR="4"
|
CLIXON_VERSION_MAJOR="4"
|
||||||
CLIXON_VERSION_MINOR="1"
|
CLIXON_VERSION_MINOR="2"
|
||||||
CLIXON_VERSION_PATCH="0"
|
CLIXON_VERSION_PATCH="0"
|
||||||
CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}\""
|
CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}.PRE\""
|
||||||
|
|
||||||
# Check CLIgen
|
# Check CLIgen
|
||||||
if test "$prefix" = "NONE"; then
|
if test "$prefix" = "NONE"; then
|
||||||
|
|
|
||||||
|
|
@ -43,9 +43,9 @@ AC_INIT(lib/clixon/clixon.h.in)
|
||||||
: ${INSTALLFLAGS="-s"}
|
: ${INSTALLFLAGS="-s"}
|
||||||
|
|
||||||
CLIXON_VERSION_MAJOR="4"
|
CLIXON_VERSION_MAJOR="4"
|
||||||
CLIXON_VERSION_MINOR="1"
|
CLIXON_VERSION_MINOR="2"
|
||||||
CLIXON_VERSION_PATCH="0"
|
CLIXON_VERSION_PATCH="0"
|
||||||
CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}\""
|
CLIXON_VERSION="\"${CLIXON_VERSION_MAJOR}.${CLIXON_VERSION_MINOR}.${CLIXON_VERSION_PATCH}.PRE\""
|
||||||
|
|
||||||
# Check CLIgen
|
# Check CLIgen
|
||||||
if test "$prefix" = "NONE"; then
|
if test "$prefix" = "NONE"; then
|
||||||
|
|
|
||||||
10
doc/FAQ.md
10
doc/FAQ.md
|
|
@ -91,11 +91,11 @@ The main example:
|
||||||
|
|
||||||
## How do I run Clixon example commands?
|
## How do I run Clixon example commands?
|
||||||
|
|
||||||
- Start a backend server: `clixon_backend -F -s init -f /usr/local/etc/example.xml`
|
- Start a backend server: `sudo clixon_backend -s init -f /usr/local/etc/example.xml`
|
||||||
- Start a cli session: `clixon_cli -f /usr/local/etc/example.xml`
|
- Start a cli session: `clixon_cli -f /usr/local/etc/example.xml`
|
||||||
- Start a netconf session: `clixon_netconf -f /usr/local/etc/example.xml`
|
- Start a netconf session: `clixon_netconf -f /usr/local/etc/example.xml`
|
||||||
- Start a restconf daemon: `sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data`
|
- Start a restconf daemon: `sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data`
|
||||||
- Send a restconf command: `curl -G http://127.0.0.1/restconf/data`
|
- Send a restconf command: `curl -X GET http://127.0.0.1/restconf/data`
|
||||||
|
|
||||||
More info in the [example](../example) directory.
|
More info in the [example](../example) directory.
|
||||||
|
|
||||||
|
|
@ -195,12 +195,12 @@ Start the clixon restconf daemon
|
||||||
sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data
|
sudo su -c "/www-data/clixon_restconf -f /usr/local/etc/example.xml " -s /bin/sh www-data
|
||||||
```
|
```
|
||||||
|
|
||||||
Then acess:
|
Then access:
|
||||||
```
|
```
|
||||||
curl -G http://127.0.0.1/restconf/data/ietf-interfaces:interfaces/interface=eth9/type
|
curl -X GET http://127.0.0.1/restconf/data/ietf-interfaces:interfaces/interface=eth0/type
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"ietf-interfaces:type": "ex:eth"
|
"ietf-interfaces:type": "clixon-example:eth"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -151,9 +151,11 @@ Start the clixon restconf daemon
|
||||||
```
|
```
|
||||||
then access using curl or wget:
|
then access using curl or wget:
|
||||||
```
|
```
|
||||||
curl -G http://127.0.0.1/restconf/data/ietf-interfaces:interfaces/interface=eth9/type
|
curl -X GET http://127.0.0.1/restconf/data/ietf-interfaces:interfaces/interface=eth1/type
|
||||||
```
|
```
|
||||||
|
|
||||||
|
More info: (restconf)[../../apps/restconf/README.md].
|
||||||
|
|
||||||
## Streams
|
## Streams
|
||||||
|
|
||||||
The example has an EXAMPLE stream notification triggering every 5s. To start a notification
|
The example has an EXAMPLE stream notification triggering every 5s. To start a notification
|
||||||
|
|
@ -178,7 +180,7 @@ cli> no notify
|
||||||
cli>
|
cli>
|
||||||
```
|
```
|
||||||
|
|
||||||
Restconf support is also supported, see (restc)[../../apps/restconf/README.md].
|
Restconf support is also supported, see (restconf)[../../apps/restconf/README.md].
|
||||||
|
|
||||||
|
|
||||||
## RPC Operations
|
## RPC Operations
|
||||||
|
|
|
||||||
|
|
@ -1028,7 +1028,7 @@ xml2json_vec(FILE *f,
|
||||||
int retval = 1;
|
int retval = 1;
|
||||||
cbuf *cb = NULL;
|
cbuf *cb = NULL;
|
||||||
|
|
||||||
if ((cb = cbuf_new()) ==NULL){
|
if ((cb = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_XML, errno, "cbuf_new");
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -1084,7 +1084,8 @@ json_xmlns_translate(yang_stmt *yspec,
|
||||||
if (xml2ns(x, NULL, &namespace0) < 0)
|
if (xml2ns(x, NULL, &namespace0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* Set xmlns="" default namespace attribute (if diff from default) */
|
/* Set xmlns="" default namespace attribute (if diff from default) */
|
||||||
if (namespace0==NULL || strcmp(namespace0, namespace)){
|
if (namespace0 == NULL ||
|
||||||
|
strcmp(namespace0, namespace)){
|
||||||
if (xmlns_set(x, NULL, namespace) < 0)
|
if (xmlns_set(x, NULL, namespace) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* and remove prefix */
|
/* and remove prefix */
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,11 @@
|
||||||
* @see https://tools.ietf.org/html/rfc6020 YANG 1.0
|
* @see https://tools.ietf.org/html/rfc6020 YANG 1.0
|
||||||
* @see https://tools.ietf.org/html/rfc7950 YANG 1.1
|
* @see https://tools.ietf.org/html/rfc7950 YANG 1.1
|
||||||
*
|
*
|
||||||
* yang_spec_parse_module
|
* CALLING ORDER OF YANG PARSE FILES
|
||||||
* \
|
* =================================
|
||||||
|
* yang_spec_parse_module
|
||||||
|
* | |
|
||||||
|
* v v v
|
||||||
* yang_spec_parse_file-> yang_parse_post->yang_parse_recurse->yang_parse_module
|
* yang_spec_parse_file-> yang_parse_post->yang_parse_recurse->yang_parse_module
|
||||||
* \ / v
|
* \ / v
|
||||||
* yang_spec_load_dir ------------------------------------> yang_parse_filename
|
* yang_spec_load_dir ------------------------------------> yang_parse_filename
|
||||||
|
|
@ -562,8 +565,8 @@ yang_find(yang_stmt *yn,
|
||||||
ys = yn->ys_stmt[i];
|
ys = yn->ys_stmt[i];
|
||||||
if (yang_keyword_get(ys) == Y_INCLUDE){
|
if (yang_keyword_get(ys) == Y_INCLUDE){
|
||||||
name = yang_argument_get(ys);
|
name = yang_argument_get(ys);
|
||||||
ym = yang_find_module_by_name(yspec, name);
|
if ((ym = yang_find_module_by_name(yspec, name)) != NULL &&
|
||||||
if ((yret = yang_find(ym, keyword, argument)) != NULL)
|
(yret = yang_find(ym, keyword, argument)) != NULL)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2330,20 +2333,12 @@ yang_expand_grouping(yang_stmt *yn)
|
||||||
* Syntax parsing. A string is input and a syntax-tree is returned (or error).
|
* Syntax parsing. A string is input and a syntax-tree is returned (or error).
|
||||||
* A variable record is also returned containing a list of (global) variable values.
|
* A variable record is also returned containing a list of (global) variable values.
|
||||||
* (cloned from cligen)
|
* (cloned from cligen)
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] str String of yang statements
|
* @param[in] str String of yang statements
|
||||||
* @param[in] name Log string, typically filename
|
* @param[in] name Log string, typically filename
|
||||||
* @param[in] ysp Yang specification. Should ave been created by caller
|
* @param[in] yspec Yang specification.
|
||||||
* using yspec_new
|
* @retval ymod Top-level yang (sub)module
|
||||||
* @retval ymod Top-level yang (sub)module
|
* @retval NULL Error encountered
|
||||||
* @retval NULL Error encountered
|
* See top of file for diagram of calling order
|
||||||
* Calling order:
|
|
||||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
|
||||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
|
|
||||||
* yang_parse_filename # Read yang file into a string
|
|
||||||
* yang_parse_file # Read yang open file descriptor into a string
|
|
||||||
* yang_parse_str # Set up yacc parser and call it given a string
|
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
|
||||||
*/
|
*/
|
||||||
static yang_stmt *
|
static yang_stmt *
|
||||||
yang_parse_str(char *str,
|
yang_parse_str(char *str,
|
||||||
|
|
@ -2442,21 +2437,60 @@ yang_parse_file(int fd,
|
||||||
return ymod; /* top-level (sub)module */
|
return ymod; /* top-level (sub)module */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Given a yang filename, extract the revision as an integer as YYYYMMDD
|
||||||
|
* @param[in] filename Filename on the form: name [+ @rev ] + .yang
|
||||||
|
* @param[out] basep "Base" filename, stripped: [+ @rev ] + .yang
|
||||||
|
* @param[out] revp Revision as YYYYMMDD (0 if not found)
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
filename2revision(const char *filename,
|
||||||
|
char **basep,
|
||||||
|
uint32_t *revp)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char *base = NULL;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
/* base = module name [+ @rev ] + .yang */
|
||||||
|
if ((base = strdup(filename)) == NULL){
|
||||||
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
clicon_debug(1, "%s %s", __FUNCTION__, base);
|
||||||
|
if ((p = rindex(base, '.')) != NULL) /* strip postfix .yang */
|
||||||
|
*p = '\0';
|
||||||
|
if ((p = index(base, '@')) != NULL){ /* extract revision date */
|
||||||
|
*p++ = '\0';
|
||||||
|
if (ys_parse_date_arg(p, revp) < 0)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (basep){
|
||||||
|
*basep = base;
|
||||||
|
base = NULL;
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
if (base)
|
||||||
|
free(base);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! No specific revision give. Match a yang file given module
|
/*! No specific revision give. Match a yang file given module
|
||||||
* @param[in] h CLICON handle
|
* @param[in] h CLICON handle
|
||||||
* @param[in] dir Directory, if NULL, look in YANG_DIR path
|
|
||||||
* @param[in] module Name of main YANG module.
|
* @param[in] module Name of main YANG module.
|
||||||
* @param[in] revision Revision or NULL
|
* @param[in] revision Revision or NULL
|
||||||
* @param[out] fbuf Buffer containing filename
|
* @param[out] revactual Actual revision (if retval=1)
|
||||||
|
* @param[out] fbuf Buffer containing filename (if retval=1)
|
||||||
|
* @retval 1 Match found, Most recent entry returned in fbuf and revactual
|
||||||
|
* @retval 0 No matching entry found
|
||||||
|
* @retval -1 Error
|
||||||
* @note for bootstrapping, dir may have to be set.
|
* @note for bootstrapping, dir may have to be set.
|
||||||
* @retval 1 Match found, Most recent entry returned in fbuf
|
|
||||||
* @retval 0 No matching entry found
|
|
||||||
* @retval -1 Error
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
yang_parse_find_match(clicon_handle h,
|
yang_parse_find_match(clicon_handle h,
|
||||||
const char *module,
|
const char *module,
|
||||||
const char *revision,
|
const char *revision,
|
||||||
|
uint32_t *revactual,
|
||||||
cbuf *fbuf)
|
cbuf *fbuf)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
|
|
@ -2515,21 +2549,13 @@ yang_parse_find_match(clicon_handle h,
|
||||||
/*! Open a file, read into a string and invoke yang parsing
|
/*! Open a file, read into a string and invoke yang parsing
|
||||||
*
|
*
|
||||||
* Similar to clicon_yang_str(), just read a file first
|
* Similar to clicon_yang_str(), just read a file first
|
||||||
* (cloned from cligen)
|
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] filename Name of file
|
* @param[in] filename Name of file
|
||||||
* @param[in] ysp Yang specification. Should have been created by caller using yspec_new
|
* @param[in] ysp Yang specification. Should have been created by caller using yspec_new
|
||||||
* @retval ymod Top-level yang (sub)module
|
* @retval ymod Top-level yang (sub)module
|
||||||
* @retval NULL Error encountered
|
* @retval NULL Error encountered
|
||||||
|
|
||||||
* The database symbols are inserted in alphabetical order.
|
* The database symbols are inserted in alphabetical order.
|
||||||
* Calling order:
|
* See top of file for diagram of calling order
|
||||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
|
||||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
|
|
||||||
* yang_parse_filename # Read yang file into a string
|
|
||||||
* yang_parse_file # Read yang open file descriptor into a string
|
|
||||||
* yang_parse_str # Set up yacc parser and call it given a string
|
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
|
||||||
*/
|
*/
|
||||||
yang_stmt *
|
yang_stmt *
|
||||||
yang_parse_filename(const char *filename,
|
yang_parse_filename(const char *filename,
|
||||||
|
|
@ -2556,6 +2582,18 @@ yang_parse_filename(const char *filename,
|
||||||
return ymod; /* top-level (sub)module */
|
return ymod; /* top-level (sub)module */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Given a (sub)module, parse all (sub)modules in turn recursively
|
||||||
|
*
|
||||||
|
* Find a yang module file, and then recursively parse all its imported modules.
|
||||||
|
* @param[in] h CLICON handle
|
||||||
|
* @param[in] module Module name
|
||||||
|
* @param[in] revision Revision (or NULL)
|
||||||
|
* @param[in] ysp Yang statement
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
*
|
||||||
|
* See top of file for diagram of calling order
|
||||||
|
*/
|
||||||
static yang_stmt *
|
static yang_stmt *
|
||||||
yang_parse_module(clicon_handle h,
|
yang_parse_module(clicon_handle h,
|
||||||
const char *module,
|
const char *module,
|
||||||
|
|
@ -2563,22 +2601,37 @@ yang_parse_module(clicon_handle h,
|
||||||
yang_stmt *ysp)
|
yang_stmt *ysp)
|
||||||
{
|
{
|
||||||
cbuf *fbuf = NULL;
|
cbuf *fbuf = NULL;
|
||||||
|
char *filename;
|
||||||
int nr;
|
int nr;
|
||||||
yang_stmt *ymod = NULL;
|
yang_stmt *ymod = NULL;
|
||||||
|
yang_stmt *yrev; /* yang revision */
|
||||||
|
uint32_t revf = 0; /* revision in filename */
|
||||||
|
uint32_t revm = 0; /* revision in parsed new module (should be same as revf) */
|
||||||
|
|
||||||
if ((fbuf = cbuf_new()) == NULL){
|
if ((fbuf = cbuf_new()) == NULL){
|
||||||
clicon_err(OE_YANG, errno, "cbuf_new");
|
clicon_err(OE_YANG, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Match a yang file with or without revision in yang-dir list */
|
/* Match a yang file with or without revision in yang-dir list */
|
||||||
if ((nr = yang_parse_find_match(h, module, revision, fbuf)) < 0)
|
if ((nr = yang_parse_find_match(h, module, revision, &revf, fbuf)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (nr == 0){
|
if (nr == 0){
|
||||||
clicon_err(OE_YANG, errno, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs", module);
|
clicon_err(OE_YANG, errno, "No yang files found matching \"%s\" in the list of CLICON_YANG_DIRs", module);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if ((ymod = yang_parse_filename(cbuf_get(fbuf), ysp)) == NULL)
|
filename = cbuf_get(fbuf);
|
||||||
|
if ((ymod = yang_parse_filename(filename, ysp)) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
if ((yrev = yang_find(ymod, Y_REVISION, NULL)) != NULL)
|
||||||
|
revm = cv_uint32_get(yrev->ys_cv);
|
||||||
|
if (filename2revision(filename, NULL, &revf) < 0)
|
||||||
|
goto done;
|
||||||
|
/* Sanity check that file revision does not match internal rev stmt */
|
||||||
|
if (revf && revm && revm != revf){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "Yang module file revision and in yang does not match: %s vs %u", filename, revm);
|
||||||
|
ymod = NULL;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
done:
|
done:
|
||||||
if (fbuf)
|
if (fbuf)
|
||||||
cbuf_free(fbuf);
|
cbuf_free(fbuf);
|
||||||
|
|
@ -2587,20 +2640,14 @@ yang_parse_module(clicon_handle h,
|
||||||
|
|
||||||
/*! Given a (sub)module, parse all (sub)modules in turn recursively
|
/*! Given a (sub)module, parse all (sub)modules in turn recursively
|
||||||
*
|
*
|
||||||
* @param[in] h CLICON handle
|
|
||||||
* @param[in] module Name of main YANG module. Or absolute file name.
|
|
||||||
* @param[in] revision Module revision date or NULL
|
|
||||||
* @param[in] ysp Yang specification. Should have been created by caller using yspec_new
|
|
||||||
* @retval ymod Top-level yang (sub)module
|
|
||||||
* @retval NULL Error encountered
|
|
||||||
* Find a yang module file, and then recursively parse all its imported modules.
|
* Find a yang module file, and then recursively parse all its imported modules.
|
||||||
* Calling order:
|
* @param[in] h CLICON handle
|
||||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
* @param[in] ymod Yang module.
|
||||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
|
* @param[in] yspec Yang specification.
|
||||||
* yang_parse_filename # Read yang file into a string
|
* @retval 0 OK
|
||||||
* yang_parse_file # Read yang open file descriptor into a string
|
* @retval -1 Error
|
||||||
* yang_parse_str # Set up yacc parser and call it given a string
|
*
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
* See top of file for diagram of calling order
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
yang_parse_recurse(clicon_handle h,
|
yang_parse_recurse(clicon_handle h,
|
||||||
|
|
@ -2646,6 +2693,11 @@ yang_parse_recurse(clicon_handle h,
|
||||||
return retval; /* top-level (sub)module */
|
return retval; /* top-level (sub)module */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @param[in] ys Yang statement
|
||||||
|
* @param[in] dummy Necessary for called in yang_apply
|
||||||
|
* @see yang_apply_fn
|
||||||
|
*/
|
||||||
static int
|
static int
|
||||||
ys_schemanode_check(yang_stmt *ys,
|
ys_schemanode_check(yang_stmt *ys,
|
||||||
void *dummy)
|
void *dummy)
|
||||||
|
|
@ -2716,9 +2768,11 @@ ys_schemanode_check(yang_stmt *ys,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Find feature and if-feature nodes, check features and remove disabled nodes
|
/*! Find feature and if-feature nodes, check features and remove disabled nodes
|
||||||
* @retval -1 Error
|
* @param[in] h CLICON handle
|
||||||
* @retval 0 Feature not enabled: remove yt
|
* @param[in] yt Yang statement
|
||||||
* @retval 1 OK
|
* @retval -1 Error
|
||||||
|
* @retval 0 Feature not enabled: remove yt
|
||||||
|
* @retval 1 OK
|
||||||
* @note On return 1 the over-lying function need to remove yt from its parent
|
* @note On return 1 the over-lying function need to remove yt from its parent
|
||||||
* @note cannot use yang_apply here since child-list is modified (destructive)
|
* @note cannot use yang_apply here since child-list is modified (destructive)
|
||||||
*/
|
*/
|
||||||
|
|
@ -2794,24 +2848,22 @@ yang_features(clicon_handle h,
|
||||||
|
|
||||||
/*! Parse top yang module including all its sub-modules. Expand and populate yang tree
|
/*! Parse top yang module including all its sub-modules. Expand and populate yang tree
|
||||||
*
|
*
|
||||||
* @param[in] h CLICON handle
|
* Perform secondary actions after yang parsing. These actions cannot be made at
|
||||||
* @param[in] filename File name containing Yang specification. Overrides module
|
* compile-time for various reasons.
|
||||||
* @param[in] module Name of main YANG module. Or absolute file name.
|
* These includes:
|
||||||
* @param[in] revision Main module revision date string or NULL
|
* - Detect imported yang specs that are not loaded and load and parse them too
|
||||||
* @param[in,out] ysp Yang specification. Should have been created by caller using yspec_new
|
* - Check cardinality of yang (that nr of children match)
|
||||||
* @retval 0 Everything OK
|
* - Check features: remove disabled
|
||||||
* @retval -1 Error encountered
|
* - "Populate" yang, which means things like initiating caches, resolving references
|
||||||
* The database symbols are inserted in alphabetical order.
|
* - Resolve types
|
||||||
* Find a yang module file, and then recursively parse all its imported modules.
|
* - Augments
|
||||||
* @note if mainmod is filename, revision is not considered.
|
* - Defaults
|
||||||
* Calling order:
|
*
|
||||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
* @param[in] h CLICON handle
|
||||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules,
|
* @param[in] yspec Yang specification.
|
||||||
* parse them and then recursively parse them
|
* @param[in] modnr Perform checks after this number, prior are already complete
|
||||||
* yang_parse_filename # Read yang file into a string
|
* @retval 0 Everything OK
|
||||||
* yang_parse_file # Read yang open file descriptor into a string
|
* @retval -1 Error encountered
|
||||||
* yang_parse_str # Set up yacc parser and call it given a string
|
|
||||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
yang_parse_post(clicon_handle h,
|
yang_parse_post(clicon_handle h,
|
||||||
|
|
@ -2884,13 +2936,12 @@ yang_parse_post(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Parse yang specification and its dependencies recursively given module
|
/*! Parse yang specification and its dependencies recursively given module
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
* @param[in] module Module name, or absolute filename (including dir)
|
* @param[in] module Module name, or absolute filename (including dir)
|
||||||
* @param[in] dir Directory where to look for modules and sub-modules
|
* @param[in] revision Revision, or NULL
|
||||||
* @param[in] revision Revision, or NULL
|
* @param[in] yspec Modules parse are added to this yangspec
|
||||||
* @param[in,out] yspec Modules parse are added to this yangspec
|
* @retval 0 OK
|
||||||
* @retval 0 OK
|
* @retval -1 Error
|
||||||
* @retval -1 Error
|
|
||||||
* @see yang_spec_parse_file
|
* @see yang_spec_parse_file
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
|
|
@ -2929,12 +2980,11 @@ yang_spec_parse_module(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Parse yang specification and its dependencies recursively given filename
|
/*! Parse yang specification and its dependencies recursively given filename
|
||||||
* @param[in] h clicon handle
|
* @param[in] h clicon handle
|
||||||
* @param[in] filename Actual filename (including dir and revision)
|
* @param[in] filename Actual filename (including dir and revision)
|
||||||
* @param[in] dir Directory for sub-modules
|
* @param[in] yspec Modules parse are added to this yangspec
|
||||||
* @param[in,out] yspec Modules parse are added to this yangspec
|
* @retval 0 OK
|
||||||
* @retval 0 OK
|
* @retval -1 Error
|
||||||
* @retval -1 Error
|
|
||||||
* @see yang_spec_parse_module for yang dir,module,revision instead of
|
* @see yang_spec_parse_module for yang dir,module,revision instead of
|
||||||
* actual filename
|
* actual filename
|
||||||
* @see yang_spec_load_dir For loading all files in a directory
|
* @see yang_spec_load_dir For loading all files in a directory
|
||||||
|
|
@ -2976,11 +3026,11 @@ yang_spec_parse_file(clicon_handle h,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Load all yang modules in directory
|
/*! Load all yang modules in directory
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] dir Load all yang modules in this directory
|
* @param[in] dir Load all yang modules in this directory
|
||||||
* @param[in,out] yspec Modules parse are added to this yangspec
|
* @param[in] yspec Modules parse are added to this yangspec
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see yang_spec_parse_file
|
* @see yang_spec_parse_file
|
||||||
* Load all yang files in a directory as primary objects.
|
* Load all yang files in a directory as primary objects.
|
||||||
* Some details if several same yang module x exists:
|
* Some details if several same yang module x exists:
|
||||||
|
|
@ -3006,10 +3056,9 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
yang_stmt *ym; /* yang module */
|
yang_stmt *ym; /* yang module */
|
||||||
yang_stmt *ym0; /* (existing) yang module */
|
yang_stmt *ym0; /* (existing) yang module */
|
||||||
yang_stmt *yrev; /* yang revision */
|
yang_stmt *yrev; /* yang revision */
|
||||||
uint32_t revf; /* revision in filename */
|
uint32_t revf = 0; /* revision in filename */
|
||||||
uint32_t revm; /* revision in parsed new module (same as revf) */
|
uint32_t revm = 0; /* revision in parsed new module (should be same as revf) */
|
||||||
uint32_t rev0; /* revision in existing module */
|
uint32_t rev0; /* revision in existing module */
|
||||||
char *s;
|
|
||||||
char *oldbase = NULL;
|
char *oldbase = NULL;
|
||||||
int taken = 0;
|
int taken = 0;
|
||||||
|
|
||||||
|
|
@ -3031,31 +3080,19 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
/* base = module name [+ @rev ] + .yang */
|
/* base = module name [+ @rev ] + .yang */
|
||||||
if (oldbase)
|
if (oldbase)
|
||||||
free(oldbase);
|
free(oldbase);
|
||||||
oldbase = base; base = NULL;
|
oldbase = base;
|
||||||
if ((base = strdup(dp[i].d_name)) == NULL){
|
base = NULL;
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
clicon_debug(1, "%s %s", __FUNCTION__, base);
|
|
||||||
*rindex(base, '.') = '\0'; /* strip postfix .yang */
|
|
||||||
/* base = module name [+ @rev]
|
|
||||||
* if it hasnt @rev then prefer it (dont check other files w @rev)
|
|
||||||
*/
|
|
||||||
revf = 0;
|
revf = 0;
|
||||||
if ((s = index(base, '@')) != NULL){
|
if (filename2revision(dp[i].d_name, &base, &revf) < 0)
|
||||||
*s++ = '\0';
|
goto done;
|
||||||
if (ys_parse_date_arg(s, &revf) < 0)
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (oldbase && strcmp(base, oldbase)) /* new yang file basename */
|
if (oldbase && strcmp(base, oldbase)) /* new yang file basename */
|
||||||
taken = 0;
|
taken = 0;
|
||||||
if (revf == 0){ /* No revision: a.yang - take that */
|
if (revf == 0) /* No revision: a.yang - take that */
|
||||||
taken = 1;
|
taken = 1;
|
||||||
}
|
|
||||||
else{ /* a@xxx.yang */
|
else{ /* a@xxx.yang */
|
||||||
if (taken)
|
if (taken)
|
||||||
continue; /* skip if already taken */
|
continue; /* skip if already taken */
|
||||||
/* is there anyone else later? */
|
/* Look forward: is there anyone else later? */
|
||||||
if (i+1<ndp && strncmp(base, dp[i+1].d_name, strlen(base)) == 0)
|
if (i+1<ndp && strncmp(base, dp[i+1].d_name, strlen(base)) == 0)
|
||||||
continue; /* same base: skip; */
|
continue; /* same base: skip; */
|
||||||
taken = 1; /* last in line and not taken */
|
taken = 1; /* last in line and not taken */
|
||||||
|
|
@ -3077,8 +3114,8 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
if ((yrev = yang_find(ym, Y_REVISION, NULL)) != NULL)
|
if ((yrev = yang_find(ym, Y_REVISION, NULL)) != NULL)
|
||||||
revm = cv_uint32_get(yrev->ys_cv);
|
revm = cv_uint32_get(yrev->ys_cv);
|
||||||
/* Sanity check that file revision does not match internal rev stmt */
|
/* Sanity check that file revision does not match internal rev stmt */
|
||||||
if (revf && revm && revm != revf){
|
if (revf && revm && revm != revf){ /* XXX */
|
||||||
clicon_err(OE_YANG, EINVAL, "Yang module file revision and in yang does not match: %s vs %u", filename, revm);
|
clicon_err(OE_YANG, EINVAL, "Yang module file revision and in yang does not match: %s(%u) vs %u", filename, revf, revm);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* If ym0 and ym exists, delete the yang with oldest revision
|
/* If ym0 and ym exists, delete the yang with oldest revision
|
||||||
|
|
|
||||||
|
|
@ -74,12 +74,12 @@ expecteq "$(curl -s -H 'Accept: application/yang-data+xml' -G http://localhost/r
|
||||||
|
|
||||||
# Should be alphabetically ordered
|
# Should be alphabetically ordered
|
||||||
new "restconf get restconf/operations. RFC8040 3.3.2 (json)"
|
new "restconf get restconf/operations. RFC8040 3.3.2 (json)"
|
||||||
expecteq "$(curl -sG http://localhost/restconf/operations)" 0 '{"operations": {"clixon-example:client-rpc": null,"clixon-example:empty": null,"clixon-example:optional": null,"clixon-example:example": null,"clixon-lib:debug": null,"clixon-lib:ping": null,"clixon-lib:get-state": null,"ietf-netconf:get-config": null,"ietf-netconf:edit-config": null,"ietf-netconf:copy-config": null,"ietf-netconf:delete-config": null,"ietf-netconf:lock": null,"ietf-netconf:unlock": null,"ietf-netconf:get": null,"ietf-netconf:close-session": null,"ietf-netconf:kill-session": null,"ietf-netconf:commit": null,"ietf-netconf:discard-changes": null,"ietf-netconf:validate": null,"clixon-rfc5277:create-subscription": null}}
|
expecteq "$(curl -sG http://localhost/restconf/operations)" 0 '{"operations":{"clixon-example:client-rpc":[null],"clixon-example:empty":[null],"clixon-example:optional":[null],"clixon-example:example":[null],"clixon-lib:debug":[null],"clixon-lib:ping":[null],"ietf-netconf:get-config":[null],"ietf-netconf:edit-config":[null],"ietf-netconf:copy-config":[null],"ietf-netconf:delete-config":[null],"ietf-netconf:lock":[null],"ietf-netconf:unlock":[null],"ietf-netconf:get":[null],"ietf-netconf:close-session":[null],"ietf-netconf:kill-session":[null],"ietf-netconf:commit":[null],"ietf-netconf:discard-changes":[null],"ietf-netconf:validate":[null],"clixon-rfc5277:create-subscription":[null]}}
|
||||||
'
|
'
|
||||||
|
|
||||||
new "restconf get restconf/operations. RFC8040 3.3.2 (xml)"
|
new "restconf get restconf/operations. RFC8040 3.3.2 (xml)"
|
||||||
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/operations)
|
ret=$(curl -s -H "Accept: application/yang-data+xml" -G http://localhost/restconf/operations)
|
||||||
expect='<operations><client-rpc xmlns="urn:example:clixon"/><empty xmlns="urn:example:clixon"/><optional xmlns="urn:example:clixon"/><example xmlns="urn:example:clixon"/><debug xmlns="http://clicon.org/lib"/><ping xmlns="http://clicon.org/lib"/><get-state xmlns="http://clicon.org/lib"/><get-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><copy-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><delete-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><lock xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><unlock xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><get xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><close-session xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><kill-session xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><commit xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><discard-changes xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><validate xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><create-subscription xmlns="urn:ietf:params:xml:ns:netmod:notification"/></operations>'
|
expect='<operations><client-rpc xmlns="urn:example:clixon"/><empty xmlns="urn:example:clixon"/><optional xmlns="urn:example:clixon"/><example xmlns="urn:example:clixon"/><debug xmlns="http://clicon.org/lib"/><ping xmlns="http://clicon.org/lib"/><get-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><edit-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><copy-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><delete-config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><lock xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><unlock xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><get xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><close-session xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><kill-session xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><commit xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><discard-changes xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><validate xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"/><create-subscription xmlns="urn:ietf:params:xml:ns:netmod:notification"/></operations>'
|
||||||
match=`echo $ret | grep -EZo "$expect"`
|
match=`echo $ret | grep -EZo "$expect"`
|
||||||
if [ -z "$match" ]; then
|
if [ -z "$match" ]; then
|
||||||
err "$expect" "$ret"
|
err "$expect" "$ret"
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ datarootdir = @datarootdir@
|
||||||
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
YANG_INSTALLDIR = @YANG_INSTALLDIR@
|
||||||
|
|
||||||
YANGSPECS = clixon-config@2019-06-05.yang
|
YANGSPECS = clixon-config@2019-06-05.yang
|
||||||
YANGSPECS += clixon-lib@2019-06-05.yang
|
YANGSPECS += clixon-lib@2019-08-13.yang
|
||||||
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
YANGSPECS += clixon-rfc5277@2008-07-01.yang
|
||||||
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
YANGSPECS += clixon-xml-changelog@2019-03-21.yang
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ module clixon-lib {
|
||||||
|
|
||||||
revision 2019-08-13 {
|
revision 2019-08-13 {
|
||||||
description
|
description
|
||||||
"get-state added for restconf content=nonconfig internal rpc";
|
"No changes (reverted change)";
|
||||||
}
|
}
|
||||||
revision 2019-06-05 {
|
revision 2019-06-05 {
|
||||||
description
|
description
|
||||||
|
|
@ -52,11 +52,6 @@ module clixon-lib {
|
||||||
description
|
description
|
||||||
"Released in Clixon 3.9";
|
"Released in Clixon 3.9";
|
||||||
}
|
}
|
||||||
import ietf-netconf {
|
|
||||||
description "for the get-state extension";
|
|
||||||
prefix nc;
|
|
||||||
}
|
|
||||||
|
|
||||||
rpc debug {
|
rpc debug {
|
||||||
description "Set debug level of backend.";
|
description "Set debug level of backend.";
|
||||||
input {
|
input {
|
||||||
|
|
@ -68,33 +63,4 @@ module clixon-lib {
|
||||||
rpc ping {
|
rpc ping {
|
||||||
description "Check aliveness of backend daemon.";
|
description "Check aliveness of backend daemon.";
|
||||||
}
|
}
|
||||||
rpc get-state {
|
|
||||||
description
|
|
||||||
"Retrieve device state information only. This is a clixon extension
|
|
||||||
to ietf-netconf to implement RESTCONF GET with attribute
|
|
||||||
content=nonconfig.
|
|
||||||
The reason is that netconf only has <get> and <get-config> neither
|
|
||||||
which retrieves state only";
|
|
||||||
|
|
||||||
reference "RFC 8040 4.8.1";
|
|
||||||
|
|
||||||
input {
|
|
||||||
anyxml filter {
|
|
||||||
description
|
|
||||||
"This parameter specifies the portion of the system
|
|
||||||
configuration and state data to retrieve.";
|
|
||||||
nc:get-filter-element-attributes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output {
|
|
||||||
anyxml data {
|
|
||||||
description
|
|
||||||
"Copy of the running datastore subset and/or state
|
|
||||||
data that matched the filter criteria (if any).
|
|
||||||
An empty data container indicates that the request did not
|
|
||||||
produce any results.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue