* Stream replay support

* RFC8040 Restconf replay support: start-time and stop-time query parameter support
    * This only applies to "native" restconf stream support, Nchan mode has different replay functionality
  * RFC5277 Netconf replay support using <startTime> and
  * Replay support is only in-memory and not persistent. External time-series DB could be added.
This commit is contained in:
Olof hagsand 2018-10-27 11:12:01 +02:00
parent 77e56868d4
commit af16760279
13 changed files with 355 additions and 65 deletions

View file

@ -815,12 +815,13 @@ from_client_delete_config(clicon_handle h,
* @param[out] cbret Return xml value cligen buffer
* @retval 0 OK
* @retval -1 Error. Send error message back to client.
* @see RFC5277 2.1
* @example:
* <create-subscription>
* <stream>RESULT</stream> # If not present, events in the default NETCONF stream will be sent.
* <filter type="xpath" select="XPATH-EXPR"/>
* <startTime/> # only for replay (NYI)
* <stopTime/> # only for replay (NYI)
* <startTime></startTime>
* <stopTime></stopTime>
* </create-subscription>
*/
static int
@ -834,10 +835,28 @@ from_client_create_subscription(clicon_handle h,
cxobj *x; /* Generic xml tree */
cxobj *xfilter; /* Filter xml tree */
char *ftype;
char *starttime = NULL;
char *stoptime = NULL;
char *selector = NULL;
struct timeval start;
struct timeval stop;
if ((x = xpath_first(xe, "//stream")) != NULL)
stream = xml_find_value(x, "body");
if ((x = xpath_first(xe, "//stopTime")) != NULL){
stoptime = xml_find_value(x, "body");
if (str2time(stoptime, &stop) < 0){
clicon_err(OE_PROTO, errno, "str2time");
goto done;
}
}
if ((x = xpath_first(xe, "//startTime")) != NULL){
starttime = xml_find_value(x, "body");
if (str2time(starttime, &start) < 0){
clicon_err(OE_PROTO, errno, "str2time");
goto done;
}
}
if ((xfilter = xpath_first(xe, "//filter")) != NULL){
if ((ftype = xml_find_value(xfilter, "type")) != NULL){
/* Only accept xpath as filter type */
@ -855,8 +874,13 @@ from_client_create_subscription(clicon_handle h,
goto done;
goto ok;
}
if (stream_cb_add(h, stream, selector, ce_event_cb, (void*)ce) < 0)
if (stream_cb_add(h, stream, selector, stoptime?&stop:NULL,
ce_event_cb, (void*)ce) < 0)
goto done;
/* Replay of this stream to specific subscription according to start and stop*/
if (starttime) /* XXX No this must be done _after_ this RPC completes */
if (stream_replay(h, stream, &start, stoptime?&stop:NULL) < 0)
goto done;
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");
ok:
retval = 0;

View file

@ -89,6 +89,8 @@ backend_terminate(clicon_handle h)
clicon_debug(1, "%s", __FUNCTION__);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
yspec_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
yspec_free(yspec);
if ((x = clicon_conf_xml(h)) != NULL)
xml_free(x);
stream_publish_exit();
@ -590,6 +592,7 @@ main(int argc,
usage(h, argv[0]);
return -1;
}
clicon_config_yang_set(h, yspecfg);
/* External NACM file? */
nacm_mode = clicon_option_str(h, "CLICON_NACM_MODE");
if (nacm_mode && strcmp(nacm_mode, "external") == 0)

View file

@ -85,6 +85,8 @@ cli_terminate(clicon_handle h)
clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
yspec_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
yspec_free(yspec);
if ((x = clicon_conf_xml(h)) != NULL)
xml_free(x);
cli_plugin_finish(h);
@ -338,7 +340,7 @@ main(int argc, char **argv)
usage(h, argv[0]);
return -1;
}
clicon_config_yang_set(h, yspecfg);
/* Now rest of options */
opterr = 0;
optind = 1;

View file

@ -280,6 +280,8 @@ netconf_terminate(clicon_handle h)
clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
yspec_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
yspec_free(yspec);
if ((x = clicon_conf_xml(h)) != NULL)
xml_free(x);
event_exit();
@ -390,7 +392,7 @@ main(int argc,
/* Find and read configfile */
if (clicon_options_main(h, yspecfg) < 0)
return -1;
clicon_config_yang_set(h, yspecfg);
/* Now rest of options */
optind = 1;
opterr = 0;

View file

@ -454,6 +454,8 @@ restconf_terminate(clicon_handle h)
clicon_rpc_close_session(h);
if ((yspec = clicon_dbspec_yang(h)) != NULL)
yspec_free(yspec);
if ((yspec = clicon_config_yang(h)) != NULL)
yspec_free(yspec);
if ((x = clicon_conf_xml(h)) != NULL)
xml_free(x);
clicon_handle_exit(h);
@ -583,6 +585,7 @@ main(int argc,
/* Find and read configfile */
if (clicon_options_main(h, yspecfg) < 0)
goto done;
clicon_config_yang_set(h, yspecfg);
stream_path = clicon_option_str(h, "CLICON_STREAM_PATH");
/* Now rest of options, some overwrite option file */
optind = 1;