* Notification event streams enhancements

* Yang 1.1 notification support
  * Event stream discovery support according to RFC 5277 Sec 3.2.5.1 (netconf) and RFC 8040 (restconf)
This commit is contained in:
Olof hagsand 2018-09-18 22:49:29 +02:00
parent f37fdb954f
commit 0631be19cb
16 changed files with 502 additions and 34 deletions

View file

@ -99,20 +99,10 @@ client_subscription_add(struct client_entry *ce,
return su;
}
static struct client_entry *
ce_find_bypid(struct client_entry *ce_list, int pid)
{
struct client_entry *ce;
for (ce = ce_list; ce; ce = ce->ce_next)
if (ce->ce_pid == pid)
return ce;
return NULL;
}
/*! Delete stream subscription from client subscription list */
static int
client_subscription_delete(struct client_entry *ce,
struct client_subscription *su0)
struct client_subscription *su0)
{
struct client_subscription *su;
struct client_subscription **su_prev;
@ -134,7 +124,8 @@ client_subscription_delete(struct client_entry *ce,
#ifdef notused /* xxx */
static struct client_subscription *
client_subscription_find(struct client_entry *ce, char *stream)
client_subscription_find(struct client_entry *ce,
char *stream)
{
struct client_subscription *su = NULL;
@ -146,6 +137,18 @@ client_subscription_find(struct client_entry *ce, char *stream)
}
#endif
static struct client_entry *
ce_find_bypid(struct client_entry *ce_list,
int pid)
{
struct client_entry *ce;
for (ce = ce_list; ce; ce = ce->ce_next)
if (ce->ce_pid == pid)
return ce;
return NULL;
}
/*! Remove client entry state
* Close down everything wrt clients (eg sockets, subscriptions)
* Finally actually remove client struct in handle
@ -258,6 +261,79 @@ from_client_get_config(clicon_handle h,
return retval;
}
static int
client_get_streams(clicon_handle h,
char *xpath,
cxobj **xtop)
{
int retval = -1;
cxobj *x = NULL;
cxobj *xc;
char *reason = NULL;
yang_spec *yspec;
cbuf *cb;
if ((yspec = clicon_dbspec_yang(h)) == NULL){
clicon_err(OE_YANG, ENOENT, "No yang spec");
goto done;
}
if (*xtop==NULL){
clicon_err(OE_CFG, ENOENT, "XML tree expected");
goto done;
}
if ((cb = cbuf_new()) == NULL){
clicon_err(OE_UNIX, 0, "clicon buffer");
goto done;
}
cprintf(cb,"<restconf-state xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf-monitoring\">");
if (stream_get_xml(h, cb) < 0)
goto done;
cprintf(cb,"</restconf-state>");
/* XXX. yspec */
if (xml_parse_string(cbuf_get(cb), NULL, &x) < 0)
goto done;
if (xml_merge(*xtop, x, yspec, &reason) < 0)
goto done;
if (reason){
while ((xc = xml_child_i(*xtop, 0)) != NULL)
xml_purge(xc);
if (netconf_operation_failed_xml(xtop, "rpc", reason)< 0)
goto done;
goto ok;
}
#ifdef notyet
/* Code complex to filter out anything that is outside of xpath */
if (xpath_vec(*xtop, "%s", &xvec, &xlen, xpath?xpath:"/") < 0)
goto done;
/* If vectors are specified then mark the nodes found and
* then filter out everything else,
* otherwise return complete tree.
*/
if (xvec != NULL){
for (i=0; i<xlen; i++)
xml_flag_set(xvec[i], XML_FLAG_MARK);
}
/* Remove everything that is not marked */
if (!xml_flag(*xtop, XML_FLAG_MARK))
if (xml_tree_prune_flagged_sub(*xtop, XML_FLAG_MARK, 1, NULL) < 0)
goto done;
/* reset flag */
if (xml_apply(*xtop, CX_ELMNT, (xml_applyfn_t*)xml_flag_reset, (void*)XML_FLAG_MARK) < 0)
goto done;
#endif
ok:
retval = 0;
done:
if (cb)
cbuf_free(cb);
if (reason)
free(reason);
if (x)
xml_free(x);
return retval;
}
/*! Internal message: get
*
* @param[in] h Clicon handle
@ -288,6 +364,11 @@ from_client_get(clicon_handle h,
}
/* Get state data from plugins as defined by plugin_statedata(), if any */
assert(xret);
#if 1 /* get netconf state data */
if ((ret = client_get_streams(h, selector, &xret)) < 0)
goto done;
#endif
clicon_err_reset();
if ((ret = clixon_plugin_statedata(h, selector, &xret)) < 0)
goto done;

View file

@ -756,6 +756,11 @@ main(int argc,
return -1;
}
if (stream_register(h, "NETCONF", "default NETCONF event stream") < 0)
goto done;
if (stream_register(h, "CLICON", "Clicon logs") < 0)
goto done;
if ((xmldb_plugin = clicon_xmldb_plugin(h)) == NULL){
clicon_log(LOG_ERR, "No xmldb plugin given (specify option CLICON_XMLDB_PLUGIN).\n");
goto done;
@ -765,10 +770,11 @@ main(int argc,
/* Connect to plugin to get a handle */
if (xmldb_connect(h) < 0)
goto done;
/* Parse db spec file */
/* Read and parse application yang specification */
if (yang_spec_main(h) == NULL)
goto done;
if (yang_spec_append(h, CLIXON_DATADIR, "ietf-restconf-monitoring", NULL)< 0)
goto done;
/* Set options: database dir and yangspec (could be hidden in connect?)*/
if (xmldb_setopt(h, "dbdir", clicon_xmldb_dir(h)) < 0)
goto done;

View file

@ -86,6 +86,8 @@ struct backend_handle {
int bh_magic; /* magic (HDR)*/
clicon_hash_t *bh_copt; /* clicon option list (HDR) */
clicon_hash_t *bh_data; /* internal clicon data (HDR) */
event_stream_t *ch_stream; /* notification streams, see clixon_stream.[ch] */
/* ------ end of common handle ------ */
struct client_entry *bh_ce_list; /* The client list */
int bh_ce_nr; /* Number of clients, just increment */

View file

@ -76,14 +76,14 @@
* @see struct clicon_handle, struct backend_handle
*/
struct cli_handle {
int cl_magic; /* magic (HDR)*/
clicon_hash_t *cl_copt; /* clicon option list (HDR) */
clicon_hash_t *cl_data; /* internal clicon data (HDR) */
int cl_magic; /* magic (HDR)*/
clicon_hash_t *cl_copt; /* clicon option list (HDR) */
clicon_hash_t *cl_data; /* internal clicon data (HDR) */
event_stream_t *cl_stream; /* notification streams, see clixon_stream.[ch] */
/* ------ end of common handle ------ */
cligen_handle cl_cligen; /* cligen handle */
cli_syntax_t *cl_stx; /* syntax structure */
cligen_handle cl_cligen; /* cligen handle */
cli_syntax_t *cl_stx; /* syntax structure */
};
/*! Return a clicon handle for other CLICON API calls

View file

@ -7,11 +7,13 @@ Ensure www-data is member of the CLICON_SOCK_GROUP (default clicon). If not, add
sudo usermod -a -G clicon www-data
```
This implementation uses FastCGI, see http://www.mit.edu/~yandros/doc/specs/fcgi-spec.html.
Define nginx config file: /etc/nginx/sites-available/default
```
server {
...
location /restconf {
location / {
root /usr/share/nginx/html/restconf;
fastcgi_pass unix:/www-data/fastcgi_restconf.sock;
include fastcgi_params;