Main example: Removed dependency of external IETF RFCs

+  * See [Can't initiate clixon_backend](https://github.com/clicon/clixon/issues/382)
This commit is contained in:
Olof hagsand 2022-11-01 12:20:30 +01:00
parent e3d621c66d
commit c2faf8b96c
6 changed files with 267 additions and 50 deletions

View file

@ -79,6 +79,8 @@ Developers may need to change their code
### Minor features ### Minor features
* Main example: Removed dependency of external IETF RFCs
* See [Can't initiate clixon_backend](https://github.com/clicon/clixon/issues/382)
* Added warning if modstate is not present in datastore if `CLICON_XMLDB_MODSTATE` is set. * Added warning if modstate is not present in datastore if `CLICON_XMLDB_MODSTATE` is set.
### Corrected Bugs ### Corrected Bugs

View file

@ -363,6 +363,7 @@ AC_MSG_RESULT(Clixon yang files are installed in ${YANG_INSTALLDIR})
# YANG_STANDARD_DIR is where clixon assumes standard IETF are # YANG_STANDARD_DIR is where clixon assumes standard IETF are
# This is NOT installed by Clixon and is not needed for core system # This is NOT installed by Clixon and is not needed for core system
# However, it is required by the main example and some of the tests # However, it is required by the main example and some of the tests
# You can download them at https://github.com/YangModels/yang
AC_ARG_WITH(yang-standard-dir, AC_ARG_WITH(yang-standard-dir,
[AS_HELP_STRING([--with-yang-standard-dir=DIR],[Directory of standard IETF/IEEE YANG specs (default: $prefix/share/yang/standard)])], [AS_HELP_STRING([--with-yang-standard-dir=DIR],[Directory of standard IETF/IEEE YANG specs (default: $prefix/share/yang/standard)])],
[YANG_STANDARD_DIR="$withval"], [YANG_STANDARD_DIR="$withval"],

View file

@ -206,6 +206,7 @@ Then access:
] ]
``` ```
Read more in the [restconf](../apps/restconf) docs. Read more in the [restconf](../apps/restconf) docs.
## What about reference documentation? ## What about reference documentation?
Clixon uses [Doxygen](http://www.doxygen.nl/index.html) for reference documentation. Clixon uses [Doxygen](http://www.doxygen.nl/index.html) for reference documentation.
You need to install doxygen and graphviz on your system. You need to install doxygen and graphviz on your system.
@ -321,6 +322,16 @@ containing the same Yang module. Clixon will prefer the one without a
revision date if such a file exists. If no file has a revision date, revision date if such a file exists. If no file has a revision date,
Clixon will prefer the newest. Clixon will prefer the newest.
## How do I download standard YANGs?
Some clixon tests rely on standard IETF YANG modules which you need to download. By default, these are in `/usr/local/share/yang/standard`. You can change this location with configure option `--with-yang-standard-dir=DIR`
To download the yang models required for some tests:
```
cd /usr/local/share/yang
git clone https://github.com/YangModels/yang
```
## How do I enable Yang features? ## How do I enable Yang features?
Yang models have features, and parts of a specification can be Yang models have features, and parts of a specification can be

View file

@ -100,7 +100,7 @@ all: $(PLUGINS)
CLISPECS = $(APPNAME)_cli.cli CLISPECS = $(APPNAME)_cli.cli
YANGSPECS = clixon-example@2020-12-01.yang YANGSPECS = clixon-example@2022-11-01.yang
# Backend plugin # Backend plugin
BE_SRC = $(APPNAME)_backend.c BE_SRC = $(APPNAME)_backend.c

View file

@ -17,11 +17,21 @@
## Background ## Background
The aim of the main clixon example is to illustrate common features The aim of the main clixon example is to illustrate common
and for internal testing. See the simpler [hello world](https://github.com/clicon/clixon-examples/tree/master/hello) if you want to start from the simplest possible example. features. See the simpler [hello
world](https://github.com/clicon/clixon-examples/tree/master/hello) if
you want to start from the simplest possible example.
See also other examples in: [clixon-examples](https://github.com/clicon/clixon-examples). See also other examples in: [clixon-examples](https://github.com/clicon/clixon-examples).
Historically the main example was also used for internal
testing. However, it proved difficult to have all test features in a
single example, therefore specific YANGs are encapsulated in the test
directory instead. Therefore, it may be that some features present in
the C plugins do not have corresponding YANG support in
clixon-example.yang. They may instead present in an internal test
YANG.
## Content ## Content
This directory contains a Clixon example used primarily as a part of the Clixon test suites. It can be used as a basis for making new Clixon applications. It contains the following files: This directory contains a Clixon example used primarily as a part of the Clixon test suites. It can be used as a basis for making new Clixon applications. It contains the following files:
@ -47,10 +57,16 @@ Before you start,
make && sudo make install make && sudo make install
``` ```
Ensure standard IETF YANG files needed for the example are in `/usr/local/share/yang`. If elsewhere, use `./configure --with-yang-standard-dir=DIR`. Example to checkout yang models: For some tests, you need to ensure standard IETF YANG files needed for the example are in `/usr/local/share/yang`. But this is not necessary just to start the main example.
If elsewhere, use `./configure --with-yang-standard-dir=DIR`. Example to checkout only standard yang models using "sparse checkout":
``` ```
# cd /usr/local/share cd /usr/local/share/yang
# git clone https://github.com/YangModels/yang git init
git remote add -f origin https://github.com/YangModels/yang
git config core.sparseCheckout true
echo "standard/" >> .git/info/sparse-checkout
echo "experimental/" >> .git/info/sparse-checkout
git pull origin main
``` ```
Start backend: Start backend:
@ -82,63 +98,40 @@ There are also many other commands available as examples. View the source file (
The following example shows how to add an interface in candidate, validate and commit it to running, then look at it (as xml) and finally delete it. The following example shows how to add an interface in candidate, validate and commit it to running, then look at it (as xml) and finally delete it.
``` ```
clixon_cli -f /usr/local/etc/example.xml clixon_cli -f /usr/local/etc/example.xml
cli> set interfaces interface eth1 ? cli> set table parameter a ?
<cr> <cr>
description A textual description of the interface. value
enabled This leaf contains the configured, desired state of the cli> set table parameter a value 42
interface.
ipv4 Parameters for the IPv4 address family.
ipv6 Parameters for the IPv6 address family.
type The type of the interface.
cli> set interfaces interface eth1 type ianaift:ip
cli> set interfaces interface eth1 enabled true
cli> set interfaces interface eth1 ipv4 address 1.2.3.4 prefix-length 24
cli> validate cli> validate
cli> commit cli> commit
cli> show configuration xml cli> show configuration xml
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"> <table xmlns="urn:example:clixon">
<interface> <parameter>
<name>eth1</name> <name>a</name>
<type>ianaift:ip</type> <value>42</value>
<enabled>true</enabled> </parameter>
<ip:ipv4 xmlns:ip="urn:ietf:params:xml:ns:yang:ietf-ip"> </table>
<ip:enabled>true</ip:enabled> cli> delete interfaces interface eth1table parameter a
<ip:forwarding>false</ip:forwarding>
<ip:address>
<ip:ip>1.2.3.4</ip:ip>
<ip:prefix-length>24</ip:prefix-length>
</ip:address>
</ip:ipv4>
</interface>
</interfaces>
cli> delete interfaces interface eth1
cli> commit cli> commit
``` ```
## Using Netconf ## Using Netconf
The following example shows how to set data using netconf: The following example shows how to set data using netconf (Use `-0` for EOM framing that can be used in shell):
``` ```
sh> clixon_netconf -qf /usr/local/etc/example.xml sh> clixon_netconf -qf /usr/local/etc/example.xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.1</capability></capabilities></hello>]]>]]> <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:netconf:base:1.0</capability></capabilities></hello>]]>]]>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="0"> <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="0">
<edit-config> <edit-config>
<target><candidate/></target> <target><candidate/></target>
<config> <config>
<interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"> <table xmlns="urn:example:clixon">
<interface> <parameter>
<name>eth1</name> <name>a</name>
<type>ianaift:ip</type> <value>42</value>
<enabled>true</enabled> </parameter>
<ipv4 xmlns="urn:ietf:params:xml:ns:yang:ietf-ip"> </table>
<address>
<ip>1.2.3.4</ip>
<prefix-length>24</prefix-length>
</address>
</ipv4>
</interface>
</interfaces>
</config> </config>
</edit-config> </edit-config>
</rpc>]]>]]> </rpc>]]>]]>
@ -156,12 +149,18 @@ Getting data:
<source><candidate/></source> <source><candidate/></source>
</get-config> </get-config>
</rpc>]]>]]> </rpc>]]>]]>
# Reply: <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2"><data><interfaces xmlns="urn:ietf:params:xml:ns:yang:ietf-interfaces"><interface><name>eth1</name><type>ianaift:ip</type><enabled>true</enabled><ip:ipv4 xmlns:ip="urn:ietf:params:xml:ns:yang:ietf-ip"><ip:enabled>true</ip:enabled><ip:forwarding>false</ip:forwarding><ip:address><ip:ip>1.2.3.4</ip:ip><ip:prefix-length>24</ip:prefix-length></ip:address></ip:ipv4></interface></interfaces></data></rpc-reply>]]>]]> # Reply: <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="2"><data><table xmlns="urn:example:clixon"><parameter><name>a</name><value>42</value></parameter></table></data></rpc-reply>]]>]]>
``` ```
Examples of a filtered GET statement: Examples of a filtered GET statement:
``` ```
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1"><get-config><source><candidate/></source><filter type="xpath" select="/if:interfaces/if:interface[if:name='eth1']" xmlns:if="urn:ietf:params:xml:ns:yang:ietf-interfaces"/></get-config></rpc>]]>]]> <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="1">
<get-config>
<source><candidate/></source>
<filter type="xpath" select="/ex:table/ex:parameter[ex:name='a']" xmlns:ex="urn:example:clixon"/>
</get-config>
</rpc>]]>]]>
``` ```
## Restconf ## Restconf
@ -251,7 +250,7 @@ Start the clixon restconf daemon
``` ```
then access using curl or wget: then access using curl or wget:
``` ```
curl -X GET http://127.0.0.1/restconf/data/ietf-interfaces:interfaces/interface=eth1/type curl -X GET http://127.0.0.1/restconf/data/clixon-example:table/parameter=a/value
``` ```
## Streams ## Streams

View file

@ -0,0 +1,204 @@
module clixon-example {
yang-version 1.1;
namespace "urn:example:clixon";
prefix ex;
import clixon-autocli{
prefix autocli;
}
description
"Clixon example used as a part of the Clixon test suite.
It can be used as a basis for making new Clixon applications.
Note, may change without updating revision, just for testing current master.
";
revision 2022-11-01 {
description "Removing dependency on standard IETF models";
}
revision 2020-12-01 {
description "Added table/parameter/value as the primary data example";
}
revision 2020-03-11 {
description "Added container around translation list. Released in Clixon 4.4.0";
}
revision 2019-11-05 {
description "Augment interface. Released in Clixon 4.3.0";
}
revision 2019-07-23 {
description "Extension e4. Released in Clixon 4.1.0";
}
revision 2019-01-13 {
description "Released in Clixon 3.9";
}
/* Generic config data */
container table{
list parameter{
key name;
leaf name{
type string;
}
leaf value{
type string;
}
leaf hidden{
type string;
autocli:hide;
}
leaf stat{
description "Inline state data for example application";
config false;
type int32;
}
}
}
/* State data (not config) for the example application*/
container state {
config false;
description "state data for the example application (must be here for example get operation)";
leaf-list op {
type string;
}
}
/* yang extension implemented by the example backend code. */
extension e4 {
description
"The first child of the ex:e4 (unknown) statement is inserted into
the module as a regular data statement. This means that 'uses bar;'
in the ex:e4 statement below is a valid data node";
argument arg;
}
grouping bar {
leaf bar{
type string;
}
}
ex:e4 arg1{
uses bar;
}
/* Example notification as used in RFC 5277 and RFC 8040 */
notification event {
description "Example notification event.";
leaf event-class {
type string;
description "Event class identifier.";
}
container reportingEntity {
description "Event specific information.";
leaf card {
type string;
description "Line card identifier.";
}
}
leaf severity {
type string;
description "Event severity description.";
}
}
rpc client-rpc {
description "Example local client-side RPC that is processed by the
the netconf/restconf and not sent to the backend.
This is a clixon implementation detail: some rpc:s
are better processed by the client for API or perf reasons";
input {
leaf x {
type string;
}
}
output {
leaf x {
type string;
}
}
}
rpc empty {
description "Smallest possible RPC with no input or output sections";
}
rpc optional {
description "Small RPC with optional input and output";
input {
leaf x {
type string;
}
}
output {
leaf x {
type string;
}
}
}
rpc example {
description "Some example input/output for testing RFC7950 7.14.
RPC simply echoes the input for debugging.";
input {
leaf x {
description
"If a leaf in the input tree has a 'mandatory' statement with
the value 'true', the leaf MUST be present in an RPC invocation.";
type string;
mandatory true;
}
leaf y {
description
"If a leaf in the input tree has a 'mandatory' statement with the
value 'true', the leaf MUST be present in an RPC invocation.";
type string;
default "42";
}
leaf-list z {
description
"If a leaf-list in the input tree has one or more default
values, the server MUST use these values (XXX not supported)";
type string;
}
leaf w {
description
"If any node has a 'when' statement that would evaluate to
'false',then this node MUST NOT be present in the input tree.
(XXX not supported)";
type string;
}
list u0 {
description "list without key";
leaf uk{
type string;
}
}
list u1 {
description "list with key";
key uk;
leaf uk{
type string;
}
leaf val{
type string;
}
}
}
output {
leaf x {
type string;
}
leaf y {
type string;
}
leaf z {
type string;
}
leaf w {
type string;
}
list u0 {
leaf uk{
type string;
}
}
list u1 {
key uk;
leaf uk{
type string;
}
leaf val{
type string;
}
}
}
}
}