7 RESTCONF
This section describes how to use RESTCONF with the Clixon controller.
Please also consult the RESTCONF section in the Clixon user manual.
7.1 Configuration
Clixon provides many different configurations for RESTCONF. The controller only supports the following:
Native TLS and http in the RESTCONF daemon. No reverse proxy is needed.
HTTP/1.1 and HTTP/2
Basic and TLS/SSL client cert authentication
Datastore configuration, not in configuration file
7.1.1 Example config
A typical RESTCONF configuration may look as follows, where a TLS on port 443 on 192.168.32.1 is configured using client-certs placed in the etc/pki/tls
directory:
<restconf xmlns="http://clicon.org/restconf">
<enable>true</enable>
<auth-type>client-certificate</auth-type>
<server-cert-path>/etc/pki/tls/certs/clixon-server-crt.pem</server-cert-path>
<server-key-path>/etc/pki/tls/private/clixon-server-key.pem</server-key-path>
<server-ca-cert-path>/etc/pki/tls/CA/clixon-ca-crt.pem</server-ca-cert-path>
<socket>
<namespace>default</namespace>
<address>192.168.32.1</address>
<port>443</port>
<ssl>true</ssl>
</socket>
</restconf>
Alternatively, you may use basic auth
You should modify the configuration above to suit you needs, thereafter install it in the Clixon datastore using one of the methods described in the next section.
7.2 Install configuration
You install the RESTCONF configuration by adding it to the datastore in one of the following methods.
7.2.1 Install using CLI
Enter the CLI and edit the RESTCONF configuration and commit it:
# clixon_cli
cli> configure
cli# set restconf enable true
cli# set restconf server-cert-path /var/tmp/./test-restconf.sh/certs/clixon-server-crt.pem
cli# set restconf server-key-path /var/tmp/./test-restconf.sh/certs/clixon-server-key.pem
cli# set restconf server-ca-cert-path /var/tmp/./test-restconf.sh/certs/clixon-ca-crt.pem
cli# set restconf socket default 0.0.0.0 443
cli# set restconf socket default 0.0.0.0 443 ssl true
cli# commit local
cli#
The commit command should (re)start the RESTCONF daemon with the new configuration. To verify that the RESTCONF is running, see Section Verify the configuration.
7.2.2 Install in datastore
If you use a startup-db or running-db you can directly edit the datastore by adding the restconf config and restart the clixon_backend
.
Add the restconf config to the datastore, such as /usr/local/var/controller/startup.d/0.xml
as follows:
<config>
...
<restconf xmlns="http://clicon.org/restconf">
<enable>true</enable>
...
</restconf>
</config>
Then restart clixon_backend
, typically using systemd:
sudo systemctl restart clixon-controller.service
7.2.3 Install using NETCONF
Send a NETCONF edit-config message to modify the restconf configuration, and then commit it:
<?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.0</capability>
</capabilities>
</hello>]]>]]>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="42">
<target>
<candidate/>
</target>
<config>
<restconf xmlns="http://clicon.org/restconf">
<enable>true</enable>
...
</restconf>
</config>
</rpc>]]>]]>
<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="42">
<commit/>
</rpc>]]>]]>
The RESTCONF daemon should be restarted with the new configuration.
7.2.4 Verify the configuration
Verify that the daemon is running using the CLI:
cli> processes restconf status
<rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
<active xmlns="http://clicon.org/lib">true</active>
<status xmlns="http://clicon.org/lib">running</status> <---
</rpc-reply>
You can also verify it via RESTCONF (fields are simplified):
POST /restconf/operations/clixon-lib:process-control HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-lib:input": {
"name":"restconf",
"operation":"status"
}
}
A reply with a successful start is:
HTTP/1.1 200
{
"clixon-lib:output": {
"active": true,
"description": "Clixon RESTCONF process",
"status": "running"
}
}
7.3 Setup
You setup the connection to one or several devices by editing the device connection data
For setup a device with IP address 172.17.0.3
and user admin
via SSH:
POST /restconf/data/clixon-controller:devices HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:device": {
"name":"test",
"enabled":"true",
"conn-type":"NETCONF_SSH",
"user":"admin",
"addr":"172.17.0.3"
}
}
You can also configure device-groups and device-profiles as described in the CLI tutotial, for example.
7.4 Transactions
Many of the controller’s RPCs return a transaction-id that indicates that the result of the RPC is not immediately available. Instead, it indicates that a new transaction has been created.
Note
RPCs returning a transaction-id are asynchronous
Transactions can be monitored in one of the following ways:
Register and wait for a notification, as described in Section notifications.
Sleep/Poll and read the status of the resulting action, such as the connection status, see Section verify connection.
Sleep/Poll and read the status of the transaction using GET.
To get the status of transaction “6” using GET send the following request:
POST /restconf/data/clixon-controller:transactions/transaction=6 HTTP/1.1
Accept: application/yang-data+json
A typical reply:
HTTP/1.1 200
{
"clixon-controller:transaction": [
{
"tid": "6",
"result": "SUCCESS", <---
...
}
]
}
Controller RPCs that create transactions are:
config-pull
controller-commit
connection-change
device-template-apply
(of type RPC)
Transactions are described in more detail in the Transaction section.
7.5 Connect
If you have setup the configuration for your devices and installed the
SSH keys, you can start connecting to them. For this, you need to invoke
the connection-change
RPC which starts a device connect transaction.
Note
You need to install SSH keys before connection establishment
The connection-change RPC takes a device or device-group as input and an operation. Example:
POST /restconf/operations/clixon-controller:connection-change HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:input": {
"device":"*",
"operation":"OPEN"
}
}
With the following reply containing a transaction-id:
HTTP/1.1 200
{
"clixon-controller:output":{
"tid":"4"
}
}
7.5.1 Verify connection
One way to verify a connection (apart from monitoring the transaction itself) is to wait and check the status of the connection using GET, as follows:
GET /restconf/data/clixon-controller:devices/device=openconfig1/conn-state HTTP/1.1
Accept: application/yang-data+json
HTTP/1.1 200
{
"clixon-controller:conn-state":"OPEN"
}
7.5.2 Select devices
You can select devices in the connect RPCs as follows:
All devices:
device: *
Individual device:
device: openconfig1
Device pattern:
device: openconfig*
Device-groups:
device-group: mygroup
Device-group pattern:
device-group: my*
7.5.3 Connect operations
The operation in the initial example is OPEN. The operations are:
Establish connections to a set of devices:
OPEN
Close connections:
CLOSE
Close and the re-open connections:
RECONNECT
Example, reconnect to all devices in device-groups starting with “my*”:
POST /restconf/operations/clixon-controller:connection-change HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:input": {
"device-group": "my*",
"operation": "RECONNECT"
}
}
7.6 Accessing device config
When devices are open, you can get, put and push device configuration.
7.6.1 GET device config
You can GET configuration from a single device as follows:
GET /restconf/data/clixon-controller:devices/device=openconfig1/config HTTP/1.1
Accept: application/yang-data+json
HTTP/1.1 200
{
"clixon-controller:config": {
"openconfig-interfaces:interfaces": {
"interface": [
{
"name": "x",
...
You can also get more specific config:
GET /restconf/data/clixon-controller:devices/device=openconfig1/\
config//openconfig-interfaces:interfaces/interface=x/config/type HTTP/1.1
Accept: application/yang-data+json
HTTP/1.1 200
{
"openconfig-interfaces:type": "iana-if-type:ethernetCsmacd"
}
7.6.2 PUT device config
To edit device configuration, use PUT, POST or PATCH and then push the changes to devices.
With RESTCONF, modifications are written to the running datastore in the controller (local commit). Thereafter, the changes are pushed to the devices using the controller-commit
RPC.
For example, change the description of an interface using PUT:
PUT /restconf/data/clixon-controller:devices/device=openconfig1/config/\
openconfig-interfaces:interfaces/interface=x/config HTTP/1.1
Content-Type: application/yang-data+json
{
"openconfig-interfaces:config": {
"name": "x",
"type": "iana-if-type:ethernetCsmacd",
"description": "My description"
}
}
HTTP/1.1 204
7.6.3 PUSH device config
Thereafter, push the changes to a device using the controller-commit
RPC:
POST /restconf/operations/clixon-controller:controller-commit HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:input": {
"device": "openconfig1",
"push": "COMMIT",
}
}
This may generate a reply as follows:
HTTP/1.1 200
{
"clixon-controller:output":{
"tid":"3"
}
}
Again, this starts an asynchronous transaction which can be monitored with methods described in Section transactions.
7.7 Notifications
The controller uses notifications to get asynchronous notifications and event streams.
For example, connection establishment as described in Section connect and commit described in Section push device config create transactions. If you want to wait for such a transaction to complete, you can register for that event stream as follows:
GET /restconf/streams/controller-transaction HTTP/1.1
Accept: text/event-stream
Cache-Control: no-cache
Connection: keep-alive
The data notification is an “SSE” / long poll event, which means that the call blocks and waits for notifications to be received:
HTTP/2 201
content-type: text/event-stream
data: <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0">
<eventTime>2025-03-06T15:30:16.710209Z</eventTime>
<controller-transaction xmlns="http://clicon.org/controller">
<tid>4</tid>
<username>clicon</username>
<result>SUCCESS</result>
</controller-transaction>
</notification>
This means that a programmer needs to create a separate session apart from the original RPC: One which waits for a notification, and one which creates the transaction using an operation.
7.8 Services
You may wish to read the the service tutotial before reading this section.
You can initate a service typically implemented in Python(PyAPI) by editing a service configuration and then applying the service using the controller-commit
RPC.
With CLI or NETCONF it is possible to edit a service in the candidate datastore and then only trigger the services that have changed. This is not possible in RESTCONF, since it does not use the candidate datastore. Instead you need to explicitly set which service has changed (or all)
7.8.1 Edit a service config
First, edit a service. You can skip this part of you just want to trigger a service unconditionally.
In the following example, edit the bar
instance of the testA
service in module myyang
(ie instance testA[a_name='bar']
.
POST /restconf/restconf/data/clixon-controller:services HTTP/1.1
Content-Type: application/yang-data+json
{
"myyang:testA": [
{
"a_name": "bar",
"params": [
"AA"
]
}
]
}
This changes the service config in the running datastore of the controller. But it does not trigger a service.
7.8.2 Trigger service code
To trigger a service, you need to send a controller-commit
RPC to
the controller. You can do this either after editing a service, or
unconditionally, such as in a periodic process.
In the following example, you trigger the service as follows:
It applies for all devices:
device:*
.You push and commit the service result to the devices:
push:COMMIT
. You could also justVALIDATE
the service in the devicesThe service is unconditionally run:
actions:FORCE
. This is the only option for RESTCONF.The datastore to work with is
source:candidate
. This is also necessary for RESTCONF.Trigger the service for a specific instance:
service-instance:testA[a_name='bar']
. You may also skip this field to trigger all services.
The corresponding operation is:
POST /restconf/operations/clixon-controller:controller-commit HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:input": {
"device": "*",
"push": "COMMIT",
"actions": "FORCE",
"source": "ds:candidate"
"service-instance":"testA[a_name='bar']"
}
}
Where a transaction id is returned:
HTTP/1.1 200
{
"clixon-controller:output":{
"tid":23
}
}
7.9 Device RPCs
You can send an RPC to devices via the controller using the device-template-apply
RPC.
7.9.1 Create template
First you create a template.
An example is the following, which is the same example as the rpc template created in the CLI as described in the CLI tutorial:
POST /restconf/data/clixon-controller:devices HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:rpc-template": [
{
"name": "stats",
"variables": {
"variable": [
{
"name": "MODULES"
}
]
},
"config": {
"clixon-lib:stats": {
"modules": "${MODULES}"
}
}
}
]
}
You can create the template by other means, such as CLI or NETCONF.
7.9.2 Send RPC
The next step is to apply the template on devices resulting in a number of RPCs sent from the controller to devices.
Example:
POST /restconf/operations/clixon-controller:device-template-apply HTTP/1.1
Content-Type: application/yang-data+json
{
"clixon-controller:input": {
"type": "RPC",
"device": "openconfig*",
"template": "stats",
"variables": [
{
"variable": {
"name": "MODULES",
"value": "true"
}
}
]
}
}
Where a transaction id is returned:
HTTP/1.1 200
{
"clixon-controller:output":{
"tid":"5"
}
}
7.9.3 Read result
A transaction has been created and the client needs to wait for results via a notification (see Section notifications) or poll for completion of the transaction:
GET /restconf/data/clixon-controller:transactions/transaction=5 HTTP/1.1
Accept: application/yang-data+json
The reply could be:
HTTP/1.1 200
{
"clixon-controller:transaction": [
{
"tid": "6",
"username": "clicon",
"result": "SUCCESS",
"devices": {
"devdata": [
{
"name": "openconfig1",
"data": {
"global": {
"xmlnr": "1570",
"yangnr": "166357"
...
Note the devdata
field which returns the reply from the RPC. That is, the reply for the stats
RPC to openconfig1
is:
"data": {
"global": {
"xmlnr": "1570",
"yangnr": "166357"
The devdata
field may contain replies from multiple devices.