1# Clixon Restconf
2
3  * [Evhtp](#evhtp)
4  * [Nginx](#nginx)
5  * [Streams](#streams)
6  * [Nchan Streams](#nchan)
7  * [Debugging](#debugging)
8
9There are two installation instructions: for libevhtp and nginx.
10
11## Evhtp
12
13Download, build and install libevhtp from source. Prereqs: libevent and cmake.
14```
15   git clone https://github.com/criticalstack/libevhtp.git
16   cd libevhtp/build
17   cmake -DEVHTP_DISABLE_REGEX=ON -DEVHTP_DISABLE_EVTHR=ON ..
18   make
19   sudo make install
20```
21
22Configure clixon with evhtp:
23```
24  ./configure --with-restconf=evhtp
25```
26
27Ensure www-data is member of the CLICON_SOCK_GROUP (default clicon). If not, add it:
28```
29  sudo usermod -a -G clicon www-data
30```
31
32## Nginx
33
34Installation instruction for Nginx. Other reverse proxies should work but are not verified.
35
36Ensure www-data is member of the CLICON_SOCK_GROUP (default clicon). If not, add it:
37```
38  sudo usermod -a -G clicon www-data
39```
40
41This implementation uses FastCGI, see http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html.
42
43Download and start nginx. For example on ubuntu:
44```
45  sudo apt install ngnix
46```
47on FreeBSD:
48```
49  sudo pkg install ngnix
50```
51
52Edit the nginx config file. (On Ubuntu: `/etc/nginx/sites-available/default`, on FreeBSD: `/usr/local/etc/nginx/sites-available/default`)
53```
54  server {
55    ...
56    location / {
57      fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
58      include fastcgi_params;
59    }
60  }
61```
62
63Start nginx daemon
64```
65  sudo /etc/init.d nginx start
66```
67Alternatively, start it via systemd:
68```
69  sudo systemctl start nginx.service
70```
71Or on FreeBSD:
72```
73  sudo service nginx start
74```
75
76## Run
77
78Start clixon backend daemon (if not already started)
79```
80  sudo clixon_backend -s init -f /usr/local/etc/example.xml
81```
82
83Start clixon restconf daemon
84```
85  sudo -u www-data -s /www-data/clixon_restconf -f /usr/local/etc/example.xml
86```
87On FreeBSD:
88```
89  sudo -u www -s /www/clixon_restconf -f /usr/local/etc/example.xml
90```
91
92Make restconf calls with curl (or other http client). Example of writing a new interface specification:
93```
94  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}}}'
95```
96
97Get the data
98```
99  curl -X GET http://127.0.0.1/restconf/data/ietf-interfaces:interfaces
100  {
101    "ietf-interfaces:interfaces": {
102      "interface": [
103        {
104          "name": "eth1",
105          "type": "clixon-example:eth",
106          "enabled": true
107        }
108      ]
109    }
110  }
111
112```
113Get the type of a specific interface:
114```
115  curl -X GET http://127.0.0.1/restconf/data/ietf-interfacesinterfaces/interface=eth1/type
116  {
117    "ietf-interfaces:type": "clixon-example:eth"
118  }
119```
120
121## Streams
122
123Clixon have two experimental restconf event stream implementations following
124RFC8040 Section 6 using SSE.  One native and one using Nginx
125nchan. The Nchan alternaitve is described in the
126next section.
127
128The [example](../../example/main/README.md) creates an EXAMPLE stream.
129
130Set the Clixon configuration options:
131```
132<CLICON_STREAM_PATH>streams</CLICON_STREAM_PATH>
133<CLICON_STREAM_URL>https://example.com</CLICON_STREAM_URL>
134<CLICON_STREAM_RETENTION>3600</CLICON_STREAM_RETENTION>
135```
136In this example, the stream EXAMPLE would be accessed with `https://example.com/streams/EXAMPLE`.
137
138The retention is configured as 1 hour, i.e., the stream replay function will only save timeseries one hour.
139
140Clixon defines an internal in-memory (not persistent) replay function
141controlled by the configure option above.
142
143You may access a restconf streams using curl.
144
145Add the following to extend the nginx configuration file with the following statements (for example):
146```
147	location /streams {
148	    fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
149	    include fastcgi_params;
150 	    proxy_http_version 1.1;
151	    proxy_set_header Connection "";
152        }
153```
154
155An example of a stream access is as follows:
156```
157> curl -H "Accept: text/event-stream" -s -X GET http://localhost/streams/EXAMPLE
158data: <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>2018-11-04T14:47:11.373124</eventTime><event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event></notification>
159
160data: <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>2018-11-04T14:47:16.375265</eventTime><event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event></notification>
161```
162
163You can also specify start and stop time. Start-time enables replay of existing samples, while stop-time is used both for replay, but also for stopping a stream at some future time.
164```
165   curl -H "Accept: text/event-stream" -s -X GET http://localhost/streams/EXAMPLE?start-time=2014-10-25T10:02:00&stop-time=2014-10-25T12:31:00
166```
167
168See (stream tests)[../test/test_streams.sh] for more examples.
169
170## Nchan
171
172As an alternative streams implementation, Nginx/Nchan can be used.
173Nginx uses pub/sub channels and can be configured in a variety of
174ways. The following uses a simple variant with one generic subscription
175channel (streams) and one publication channel (pub).
176
177The advantage with Nchan is the large eco-system around Nginx and Nchan.
178
179Native mode and Nchan mode can co-exist, but the publish URL of Nchan should be different from the streams URL of the native streams.
180
181Nchan mode does not use Clixon retention, since it uses its own replay mechanism.
182
183Download and install nchan, see (https://nchan.io/#install).
184
185Add the following to extend the Nginx configuration file with the following statements (example):
186```
187        location ~ /sub/(\w+)$ {
188            nchan_subscriber;
189            nchan_channel_id $1; #first capture of the location match
190        }
191        location ~ /pub/(\w+)$ {
192            nchan_publisher;
193            nchan_channel_id $1; #first capture of the location match
194        }
195```
196
197Configure clixon with `--enable-publish` which enables curl code for
198publishing streams to nchan.
199
200You also need to configure CLICON_STREAM_PUB to enable pushing notifications to Nginx/Nchan. Example:
201```
202<CLICON_STREAM_PUB>http://localhost/pub</CLICON_STREAM_PUB>
203```
204Clicon will then publish events from stream EXAMPLE to `http://localhost/pub/EXAMPLE
205
206Access the event stream EXAMPLE using curl:
207```
208   curl -H "Accept: text/event-stream" -s -X GET http://localhost/streams/EXAMPLE
209: hi
210
211id: 1541344320:0
212data: <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>2018-11-04T15:12:00.435769</eventTime><event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event></notification>
213
214id: 1541344325:0
215data: <notification xmlns="urn:ietf:params:xml:ns:netconf:notification:1.0"><eventTime>2018-11-04T15:12:05.446425</eventTime><event><event-class>fault</event-class><reportingEntity><card>Ethernet0</card></reportingEntity><severity>major</severity></event></notification>
216
217```
218Note that the SSE stream output is different than for native streams, and that `Last-Event-Id` is used for replay:
219```
220curl -H "Accept: text/event-stream" -H "Last-Event-ID: 1539961709:0" -s -X GET http://localhost/streams/EXAMPLE
221```
222
223See (https://nchan.io/#eventsource) on more info on how to access an SSE sub endpoint.
224
225## Debugging
226
227Start the restconf fastcgi program with debug flag:
228```
229sudo su -c "/www-data/clixon_restconf -D 1 -f /usr/local/etc/example.xml" -s /bin/sh www-data
230```
231Look at syslog:
232```
233tail -f /var/log/syslog | grep clixon_restconf
234```
235
236Send command:
237```
238curl -G http://127.0.0.1/restconf/data/*
239```
240
241You can also run restconf in a debugger.
242```
243sudo gdb /www-data/clixon_restconf
244(gdb) run -D 1 -f /usr/local/etc/example.xml
245```
246but you need to ensure /www-data/fastcgi_restconf.sock has the following access (may need to be done after restconf has started)
247```
248rwxr-xr-x 1 www-data www-data 0 sep 22 11:46 /www-data/fastcgi_restconf.sock
249```
250
251You can set debug level of the backend via restconf:
252```
253   curl -is -X POST -H "Content-Type: application/yang-data+json" -d '{"clixon-lib:input":{"level":1}}' http://localhost/restconf/operations/clixon-lib:debug
254```
255