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:
parent
e3d621c66d
commit
c2faf8b96c
6 changed files with 267 additions and 50 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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"],
|
||||||
|
|
|
||||||
11
doc/FAQ.md
11
doc/FAQ.md
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
204
example/main/clixon-example@2022-11-01.yang
Normal file
204
example/main/clixon-example@2022-11-01.yang
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue