netconf error handling and test summary script
This commit is contained in:
parent
f872c7e295
commit
861300d6c0
23 changed files with 331 additions and 189 deletions
|
|
@ -20,7 +20,8 @@
|
||||||
* Openconfig yang specs parsed: https://github.com/openconfig/public
|
* Openconfig yang specs parsed: https://github.com/openconfig/public
|
||||||
* Improved "unknown" handling
|
* Improved "unknown" handling
|
||||||
* More precise Yang validation and better error messages
|
* More precise Yang validation and better error messages
|
||||||
* For Example, adding bad-, missing-, or unknown-element error messages, etc instead of operation-failed
|
* Example: adding bad-, missing-, or unknown-element error messages, etc instead of operation-failed, bad-element instead of "yang node not found", etc.
|
||||||
|
*
|
||||||
* Yang load file configure options changed
|
* Yang load file configure options changed
|
||||||
* `CLICON_YANG_DIR` is changed from a single directory to a path of directories
|
* `CLICON_YANG_DIR` is changed from a single directory to a path of directories
|
||||||
* Note CLIXON_DATADIR (=/usr/local/share/clixon) need to be in the list
|
* Note CLIXON_DATADIR (=/usr/local/share/clixon) need to be in the list
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
* (Duplicated. Also in netconf_*.h)
|
* (Duplicated. Also in netconf_*.h)
|
||||||
*/
|
*/
|
||||||
int netconf_output(int s, cbuf *xf, char *msg);
|
int netconf_output(int s, cbuf *xf, char *msg);
|
||||||
|
int netconf_output_encap(int s, cbuf *xf, char *msg);
|
||||||
|
|
||||||
int netconf_xpath(cxobj *xsearch,
|
int netconf_xpath(cxobj *xsearch,
|
||||||
cxobj *xfilter,
|
cxobj *xfilter,
|
||||||
|
|
|
||||||
|
|
@ -182,9 +182,9 @@ netconf_get_target(cxobj *xn,
|
||||||
* @param[in] s
|
* @param[in] s
|
||||||
* @param[in] cb Cligen buffer that contains the XML message
|
* @param[in] cb Cligen buffer that contains the XML message
|
||||||
* @param[in] msg Only for debug
|
* @param[in] msg Only for debug
|
||||||
* @note Assumes "cb" contains valid XML, ie encoding is correct. This is done
|
* @retval 0 OK
|
||||||
* if it is output by a xml render routine (xml_print et al), but NOT
|
* @retval -1 Error
|
||||||
* otherwise.
|
* @see netconf_output_encap for function with encapsulation
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_output(int s,
|
netconf_output(int s,
|
||||||
|
|
@ -216,3 +216,34 @@ netconf_output(int s,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Encapsulate and send outgoing netconf packet as cbuf on socket
|
||||||
|
* @param[in] s
|
||||||
|
* @param[in] cb Cligen buffer that contains the XML message
|
||||||
|
* @param[in] msg Only for debug
|
||||||
|
* @retval 0 OK
|
||||||
|
* @retval -1 Error
|
||||||
|
* @note Assumes "cb" contains valid XML
|
||||||
|
* @see netconf_output without encapsulation
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
netconf_output_encap(int s,
|
||||||
|
cbuf *cb,
|
||||||
|
char *msg)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
cbuf *cb1 = NULL;
|
||||||
|
|
||||||
|
if ((cb1 = cbuf_new()) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "cbuf_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
add_preamble(cb1);
|
||||||
|
cprintf(cb1, "%s", cbuf_get(cb));
|
||||||
|
add_postamble(cb1);
|
||||||
|
retval = netconf_output(s, cb1, msg);
|
||||||
|
done:
|
||||||
|
if (cb1)
|
||||||
|
cbuf_free(cb1);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,5 +75,6 @@ int add_error_preamble(cbuf *xf, char *reason);
|
||||||
char *netconf_get_target(cxobj *xn, char *path);
|
char *netconf_get_target(cxobj *xn, char *path);
|
||||||
int add_error_postamble(cbuf *xf);
|
int add_error_postamble(cbuf *xf);
|
||||||
int netconf_output(int s, cbuf *xf, char *msg);
|
int netconf_output(int s, cbuf *xf, char *msg);
|
||||||
|
int netconf_output_encap(int s, cbuf *cb, char *msg);
|
||||||
|
|
||||||
#endif /* _NETCONF_LIB_H_ */
|
#endif /* _NETCONF_LIB_H_ */
|
||||||
|
|
|
||||||
|
|
@ -112,7 +112,7 @@ process_incoming_packet(clicon_handle h,
|
||||||
free(str0);
|
free(str0);
|
||||||
if (netconf_operation_failed(cbret, "rpc", "internal error")< 0)
|
if (netconf_operation_failed(cbret, "rpc", "internal error")< 0)
|
||||||
goto done;
|
goto done;
|
||||||
netconf_output(1, cbret, "rpc-error");
|
netconf_output_encap(1, cbret, "rpc-error");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
free(str0);
|
free(str0);
|
||||||
|
|
@ -121,7 +121,7 @@ process_incoming_packet(clicon_handle h,
|
||||||
if ((ret = xml_yang_validate_rpc(xrpc, cbret)) < 0)
|
if ((ret = xml_yang_validate_rpc(xrpc, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
netconf_output(1, cbret, "rpc-error");
|
netconf_output_encap(1, cbret, "rpc-error");
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -157,11 +157,8 @@ process_incoming_packet(clicon_handle h,
|
||||||
if (xml_addsub(xc, xa2) < 0)
|
if (xml_addsub(xc, xa2) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
add_preamble(cbret);
|
|
||||||
|
|
||||||
clicon_xml2cbuf(cbret, xml_child_i(xret,0), 0, 0);
|
clicon_xml2cbuf(cbret, xml_child_i(xret,0), 0, 0);
|
||||||
add_postamble(cbret);
|
if (netconf_output_encap(1, cbret, "rpc-reply") < 0){
|
||||||
if (netconf_output(1, cbret, "rpc-reply") < 0){
|
|
||||||
cbuf_free(cbret);
|
cbuf_free(cbret);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -776,12 +776,10 @@ netconf_notification_cb(int s,
|
||||||
clicon_err(OE_PLUGIN, errno, "cbuf_new");
|
clicon_err(OE_PLUGIN, errno, "cbuf_new");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
add_preamble(cb); /* Make it well-formed netconf xml */
|
|
||||||
if (clicon_xml2cbuf(cb, xn, 0, 0) < 0)
|
if (clicon_xml2cbuf(cb, xn, 0, 0) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
add_postamble(cb);
|
|
||||||
/* Send it to listening client on stdout */
|
/* Send it to listening client on stdout */
|
||||||
if (netconf_output(1, cb, "notification") < 0){
|
if (netconf_output_encap(1, cb, "notification") < 0){
|
||||||
cbuf_free(cb);
|
cbuf_free(cb);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
@ -925,13 +923,13 @@ netconf_application_rpc(clicon_handle h,
|
||||||
if ((ret = xml_yang_validate_all_top(xn, cbret)) < 0)
|
if ((ret = xml_yang_validate_all_top(xn, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
netconf_output(1, cbret, "rpc-error");
|
netconf_output_encap(1, cbret, "rpc-error");
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((ret = xml_yang_validate_add(xn, cbret)) < 0)
|
if ((ret = xml_yang_validate_add(xn, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0){
|
if (ret == 0){
|
||||||
netconf_output(1, cbret, "rpc-error");
|
netconf_output_encap(1, cbret, "rpc-error");
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -450,10 +450,12 @@ api_return_err(clicon_handle h,
|
||||||
else
|
else
|
||||||
if (xml2json_cbuf(cb, xerr, pretty) < 0)
|
if (xml2json_cbuf(cb, xerr, pretty) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
clicon_debug(1, "%s code:%d err:%s", __FUNCTION__, code, cbuf_get(cb));
|
||||||
FCGX_SetExitStatus(code, r->out); /* Created */
|
FCGX_SetExitStatus(code, r->out); /* Created */
|
||||||
FCGX_FPrintF(r->out, "Status: %d %s\r\n", code, reason_phrase);
|
FCGX_FPrintF(r->out, "Status: %d %s\r\n", code, reason_phrase);
|
||||||
FCGX_FPrintF(r->out, "Content-Type: application/yang-data+%s\r\n\r\n",
|
FCGX_FPrintF(r->out, "Content-Type: application/yang-data+%s\r\n\r\n",
|
||||||
use_xml?"xml":"json");
|
use_xml?"xml":"json");
|
||||||
|
|
||||||
if (use_xml){
|
if (use_xml){
|
||||||
if (pretty){
|
if (pretty){
|
||||||
FCGX_FPrintF(r->out, " <errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">\n", cbuf_get(cb));
|
FCGX_FPrintF(r->out, " <errors xmlns=\"urn:ietf:params:xml:ns:yang:ietf-restconf\">\n", cbuf_get(cb));
|
||||||
|
|
|
||||||
|
|
@ -1118,15 +1118,8 @@ api_operations_post(clicon_handle h,
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if ((yrpc = yang_find((yang_node*)ys, Y_RPC, id)) == NULL){
|
if ((yrpc = yang_find((yang_node*)ys, Y_RPC, id)) == NULL){
|
||||||
if (netconf_operation_failed_xml(&xerr, "protocol", "yang node not found") < 0)
|
clicon_debug(1, "%s rpc %s not found", __FUNCTION__, id);
|
||||||
goto done;
|
if (netconf_missing_element_xml(&xerr, "application", id, "RPC not defined") < 0)
|
||||||
if ((xe = xpath_first(xerr, "rpc-error")) != NULL)
|
|
||||||
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
|
|
||||||
goto done;
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
if (yrpc == NULL){
|
|
||||||
if (netconf_operation_failed_xml(&xerr, "protocol", "yang node not found") < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if ((xe = xpath_first(xerr, "rpc-error")) != NULL)
|
if ((xe = xpath_first(xerr, "rpc-error")) != NULL)
|
||||||
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
|
if (api_return_err(h, r, xe, pretty, use_xml) < 0)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,10 @@ module example {
|
||||||
}
|
}
|
||||||
/* Translation function example - See also example_cli */
|
/* Translation function example - See also example_cli */
|
||||||
list translate{
|
list translate{
|
||||||
|
key k;
|
||||||
|
leaf k{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
leaf value{
|
leaf value{
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
|
|
@ -73,6 +77,57 @@ module example {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rpc empty {
|
||||||
|
description "Smallest possible RPC with no input or output";
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
when "/translate/k=5/value='w'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output {
|
||||||
|
leaf x {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf y {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf z {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf w {
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
rpc debug {
|
rpc debug {
|
||||||
description "Set debug level of backend. XXX should be in clixon-config";
|
description "Set debug level of backend. XXX should be in clixon-config";
|
||||||
input {
|
input {
|
||||||
|
|
|
||||||
|
|
@ -47,8 +47,11 @@ int netconf_missing_attribute(cbuf *cb, char *type, char *info, char *message);
|
||||||
int netconf_bad_attribute(cbuf *cb, char *type, char *info, char *message);
|
int netconf_bad_attribute(cbuf *cb, char *type, char *info, char *message);
|
||||||
int netconf_unknown_attribute(cbuf *cb, char *type, char *info, char *message);
|
int netconf_unknown_attribute(cbuf *cb, char *type, char *info, char *message);
|
||||||
int netconf_missing_element(cbuf *cb, char *type, char *element, char *message);
|
int netconf_missing_element(cbuf *cb, char *type, char *element, char *message);
|
||||||
|
int netconf_missing_element_xml(cxobj **xret, char *type, char *element, char *message);
|
||||||
int netconf_bad_element(cbuf *cb, char *type, char *info, char *element);
|
int netconf_bad_element(cbuf *cb, char *type, char *info, char *element);
|
||||||
|
int netconf_bad_element_xml(cxobj **xret, char *type, char *info, char *element);
|
||||||
int netconf_unknown_element(cbuf *cb, char *type, char *element, char *message);
|
int netconf_unknown_element(cbuf *cb, char *type, char *element, char *message);
|
||||||
|
int netconf_unknown_element_xml(cxobj **xret, char *type, char *element, char *message);
|
||||||
int netconf_unknown_namespace(cbuf *cb, char *type, char *info, char *message);
|
int netconf_unknown_namespace(cbuf *cb, char *type, char *info, char *message);
|
||||||
int netconf_access_denied(cbuf *cb, char *type, char *message);
|
int netconf_access_denied(cbuf *cb, char *type, char *message);
|
||||||
int netconf_access_denied_xml(cxobj **xret, char *type, char *message);
|
int netconf_access_denied_xml(cxobj **xret, char *type, char *message);
|
||||||
|
|
|
||||||
|
|
@ -307,6 +307,45 @@ netconf_unknown_attribute(cbuf *cb,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Common Netconf element XML tree according to RFC 6241 App A
|
||||||
|
* @param[out] xret Error XML tree. Free with xml_free after use
|
||||||
|
* @param[in] type Error type: "application" or "protocol"
|
||||||
|
* @param[in] tag Error tag
|
||||||
|
* @param[in] element bad-element xml
|
||||||
|
* @param[in] message Error message
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
netconf_element_xml_common(cxobj **xret,
|
||||||
|
char *type,
|
||||||
|
char *tag,
|
||||||
|
char *element,
|
||||||
|
char *message)
|
||||||
|
{
|
||||||
|
int retval =-1;
|
||||||
|
cxobj *xerr;
|
||||||
|
|
||||||
|
if (*xret == NULL){
|
||||||
|
if ((*xret = xml_new("rpc-reply", NULL, NULL)) == NULL)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
else if (xml_name_set(*xret, "rpc-reply") < 0)
|
||||||
|
goto done;
|
||||||
|
if ((xerr = xml_new("rpc-error", *xret, NULL)) == NULL)
|
||||||
|
goto done;
|
||||||
|
if (xml_parse_va(&xerr, NULL, "<error-type>%s</error-type>"
|
||||||
|
"<error-tag>%s</error-tag>"
|
||||||
|
"<error-info><bad-element>%s</bad-element></error-info>"
|
||||||
|
"<error-severity>error</error-severity>",
|
||||||
|
type, tag, element) < 0)
|
||||||
|
goto done;
|
||||||
|
if (message && xml_parse_va(&xerr, NULL, "<error-message>%s</error-message>",
|
||||||
|
message) < 0)
|
||||||
|
goto done;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Create Netconf missing-element error XML tree according to RFC 6241 App A
|
/*! Create Netconf missing-element error XML tree according to RFC 6241 App A
|
||||||
*
|
*
|
||||||
* An expected element is missing.
|
* An expected element is missing.
|
||||||
|
|
@ -322,31 +361,33 @@ netconf_missing_element(cbuf *cb,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
if (cprintf(cb, "<rpc-reply><rpc-error>"
|
if (netconf_element_xml_common(&xret, type, "missing-element", element, message) < 0)
|
||||||
"<error-type>%s</error-type>"
|
goto done;
|
||||||
"<error-tag>missing-element</error-tag>"
|
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
|
||||||
"<error-info><bad-element>%s</bad-element></error-info>"
|
|
||||||
"<error-severity>error</error-severity>",
|
|
||||||
type, element) <0)
|
|
||||||
goto err;
|
|
||||||
if (message){
|
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
|
|
||||||
goto err;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (encstr)
|
if (xret)
|
||||||
free(encstr);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
err:
|
}
|
||||||
clicon_err(OE_XML, errno, "cprintf");
|
|
||||||
goto done;
|
|
||||||
|
/*! Create Netconf missing-element error XML tree according to RFC 6241 App A
|
||||||
|
* @param[out] xret Error XML tree. Free with xml_free after use
|
||||||
|
* @param[in] type Error type: "application" or "protocol"
|
||||||
|
* @param[in] element bad-element xml
|
||||||
|
* @param[in] message Error message
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
netconf_missing_element_xml(cxobj **xret,
|
||||||
|
char *type,
|
||||||
|
char *element,
|
||||||
|
char *message)
|
||||||
|
{
|
||||||
|
return netconf_element_xml_common(xret, type, "missing-element", element, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf bad-element error XML tree according to RFC 6241 App A
|
/*! Create Netconf bad-element error XML tree according to RFC 6241 App A
|
||||||
|
|
@ -365,31 +406,25 @@ netconf_bad_element(cbuf *cb,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
if (cprintf(cb, "<rpc-reply><rpc-error>"
|
if (netconf_element_xml_common(&xret, type, "bad-element", element, message) < 0)
|
||||||
"<error-type>%s</error-type>"
|
goto done;
|
||||||
"<error-tag>bad-element</error-tag>"
|
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
|
||||||
"<error-info><bad-element>%s</bad-element></error-info>"
|
|
||||||
"<error-severity>error</error-severity>",
|
|
||||||
type, element) <0)
|
|
||||||
goto err;
|
|
||||||
if (message){
|
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
|
|
||||||
goto err;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (encstr)
|
if (xret)
|
||||||
free(encstr);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
err:
|
}
|
||||||
clicon_err(OE_XML, errno, "cprintf");
|
int
|
||||||
goto done;
|
netconf_bad_element_xml(cxobj **xret,
|
||||||
|
char *type,
|
||||||
|
char *element,
|
||||||
|
char *message)
|
||||||
|
{
|
||||||
|
return netconf_element_xml_common(xret, type, "bad-element", element, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf unknown-element error XML tree according to RFC 6241 App A
|
/*! Create Netconf unknown-element error XML tree according to RFC 6241 App A
|
||||||
|
|
@ -407,31 +442,25 @@ netconf_unknown_element(cbuf *cb,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
if (cprintf(cb, "<rpc-reply><rpc-error>"
|
if (netconf_element_xml_common(&xret, type, "unknown-element", element, message) < 0)
|
||||||
"<error-type>%s</error-type>"
|
goto done;
|
||||||
"<error-tag>unknown-element</error-tag>"
|
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
|
||||||
"<error-info><bad-element>%s</bad-element></error-info>"
|
|
||||||
"<error-severity>error</error-severity>",
|
|
||||||
type, element) <0)
|
|
||||||
goto err;
|
|
||||||
if (message){
|
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
|
|
||||||
goto err;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (encstr)
|
if (xret)
|
||||||
free(encstr);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
err:
|
}
|
||||||
clicon_err(OE_XML, errno, "cprintf");
|
int
|
||||||
goto done;
|
netconf_unknown_element_xml(cxobj **xret,
|
||||||
|
char *type,
|
||||||
|
char *element,
|
||||||
|
char *message)
|
||||||
|
{
|
||||||
|
return netconf_element_xml_common(xret, type, "unknown-element", element, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf unknown-namespace error XML tree according to RFC 6241 App A
|
/*! Create Netconf unknown-namespace error XML tree according to RFC 6241 App A
|
||||||
|
|
@ -476,13 +505,14 @@ netconf_unknown_namespace(cbuf *cb,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf access-denied error XML tree according to RFC 6241 App A
|
/*! Create Netconf access-denied error cbuf according to RFC 6241 App A
|
||||||
*
|
*
|
||||||
* Access to the requested protocol operation or data model is denied because
|
* Access to the requested protocol operation or data model is denied because
|
||||||
* authorization failed.
|
* authorization failed.
|
||||||
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
||||||
* @param[in] type Error type: "application" or "protocol"
|
* @param[in] type Error type: "application" or "protocol"
|
||||||
* @param[in] message Error message
|
* @param[in] message Error message
|
||||||
|
* @see netconf_access_denied_xml Same but returns XML tree
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_access_denied(cbuf *cb,
|
netconf_access_denied(cbuf *cb,
|
||||||
|
|
@ -490,39 +520,33 @@ netconf_access_denied(cbuf *cb,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
if (cprintf(cb, "<rpc-reply><rpc-error>"
|
if (netconf_access_denied_xml(&xret, type, message) < 0)
|
||||||
"<error-type>%s</error-type>"
|
goto done;
|
||||||
"<error-tag>access-denied</error-tag>"
|
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
|
||||||
"<error-severity>error</error-severity>",
|
|
||||||
type) <0)
|
|
||||||
goto err;
|
|
||||||
if (message){
|
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
|
|
||||||
goto err;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (encstr)
|
if (xret)
|
||||||
free(encstr);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
err:
|
|
||||||
clicon_err(OE_XML, errno, "cprintf");
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf access-denied error XML tree according to RFC 6241 App A
|
/*! Create Netconf access-denied error XML tree according to RFC 6241 App A
|
||||||
*
|
*
|
||||||
* Access to the requested protocol operation or data model is denied because
|
* Access to the requested protocol operation or data model is denied because
|
||||||
* authorization failed.
|
* authorization failed.
|
||||||
* @param[out] xret Error XML tree
|
* @param[out] xret Error XML tree. Free with xml_free after use
|
||||||
* @param[in] type Error type: "application" or "protocol"
|
* @param[in] type Error type: "application" or "protocol"
|
||||||
* @param[in] message Error message
|
* @param[in] message Error message
|
||||||
|
* @code
|
||||||
|
* cxobj *xret = NULL;
|
||||||
|
* if (netconf_access_denied_xml(&xret, "protocol", "Unauthorized") < 0)
|
||||||
|
* err;
|
||||||
|
* xml_free(xret);
|
||||||
|
* @endcode
|
||||||
|
* @see netconf_access_denied Same but returns cligen buffer
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_access_denied_xml(cxobj **xret,
|
netconf_access_denied_xml(cxobj **xret,
|
||||||
|
|
@ -795,6 +819,7 @@ netconf_operation_not_supported(cbuf *cb,
|
||||||
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
||||||
* @param[in] type Error type: "rpc", "application" or "protocol"
|
* @param[in] type Error type: "rpc", "application" or "protocol"
|
||||||
* @param[in] message Error message
|
* @param[in] message Error message
|
||||||
|
* @see netconf_operation_failed_xml Same but returns XML tree
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_operation_failed(cbuf *cb,
|
netconf_operation_failed(cbuf *cb,
|
||||||
|
|
@ -802,30 +827,17 @@ netconf_operation_failed(cbuf *cb,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
if (cprintf(cb, "<rpc-reply><rpc-error>"
|
if (netconf_operation_failed_xml(&xret, type, message) < 0)
|
||||||
"<error-type>%s</error-type>"
|
goto done;
|
||||||
"<error-tag>operation-failed</error-tag>"
|
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
|
||||||
"<error-severity>error</error-severity>",
|
|
||||||
type) <0)
|
|
||||||
goto err;
|
|
||||||
if (message){
|
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cprintf(cb, "</rpc-error></rpc-reply>") < 0)
|
|
||||||
goto err;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (encstr)
|
if (xret)
|
||||||
free(encstr);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
err:
|
|
||||||
clicon_err(OE_XML, errno, "cprintf");
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf operation-failed error XML tree according to RFC 6241 App A
|
/*! Create Netconf operation-failed error XML tree according to RFC 6241 App A
|
||||||
|
|
@ -835,6 +847,13 @@ netconf_operation_failed(cbuf *cb,
|
||||||
* @param[out] xret Error XML tree
|
* @param[out] xret Error XML tree
|
||||||
* @param[in] type Error type: "rpc", "application" or "protocol"
|
* @param[in] type Error type: "rpc", "application" or "protocol"
|
||||||
* @param[in] message Error message
|
* @param[in] message Error message
|
||||||
|
* @code
|
||||||
|
* cxobj *xret = NULL;
|
||||||
|
* if (netconf_operation_failed_xml(&xret, "protocol", "Unauthorized") < 0)
|
||||||
|
* err;
|
||||||
|
* xml_free(xret);
|
||||||
|
* @endcode
|
||||||
|
* @see netconf_operation_failed Same but returns cligen buffer
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_operation_failed_xml(cxobj **xret,
|
netconf_operation_failed_xml(cxobj **xret,
|
||||||
|
|
@ -872,35 +891,24 @@ netconf_operation_failed_xml(cxobj **xret,
|
||||||
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
* @param[out] cb CLIgen buf. Error XML is written in this buffer
|
||||||
* @param[in] message Error message
|
* @param[in] message Error message
|
||||||
* @note New in :base:1.1
|
* @note New in :base:1.1
|
||||||
|
* @see netconf_malformed_message_xml Same but returns XML tree
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_malformed_message(cbuf *cb,
|
netconf_malformed_message(cbuf *cb,
|
||||||
char *message)
|
char *message)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *encstr = NULL;
|
cxobj *xret = NULL;
|
||||||
|
|
||||||
if (cprintf(cb, "<rpc-reply><rpc-error>"
|
if (netconf_malformed_message_xml(&xret, message) < 0)
|
||||||
"<error-type>rpc</error-type>"
|
goto done;
|
||||||
"<error-tag>malformed-message</error-tag>"
|
if (clicon_xml2cbuf(cb, xret, 0, 0) < 0)
|
||||||
"<error-severity>error</error-severity>") <0)
|
|
||||||
goto err;
|
|
||||||
if (message){
|
|
||||||
if (xml_chardata_encode(&encstr, "%s", message) < 0)
|
|
||||||
goto done;
|
goto done;
|
||||||
if (cprintf(cb, "<error-message>%s</error-message>", encstr) < 0)
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (cprintf(cb, "</rpc-error></rpc-reply>") <0)
|
|
||||||
goto err;
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (encstr)
|
if (xret)
|
||||||
free(encstr);
|
xml_free(xret);
|
||||||
return retval;
|
return retval;
|
||||||
err:
|
|
||||||
clicon_err(OE_XML, errno, "cprintf");
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Create Netconf malformed-message error XML tree according to RFC 6241 App A
|
/*! Create Netconf malformed-message error XML tree according to RFC 6241 App A
|
||||||
|
|
@ -911,6 +919,13 @@ netconf_malformed_message(cbuf *cb,
|
||||||
* @param[out] xret Error XML tree
|
* @param[out] xret Error XML tree
|
||||||
* @param[in] message Error message
|
* @param[in] message Error message
|
||||||
* @note New in :base:1.1
|
* @note New in :base:1.1
|
||||||
|
* @code
|
||||||
|
* cxobj *xret = NULL;
|
||||||
|
* if (netconf_malformed_message_xml(&xret, "Unauthorized") < 0)
|
||||||
|
* err;
|
||||||
|
* xml_free(xret);
|
||||||
|
* @endcode
|
||||||
|
* @see netconf_malformed_message Same but returns cligen buffer
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
netconf_malformed_message_xml(cxobj **xret,
|
netconf_malformed_message_xml(cxobj **xret,
|
||||||
|
|
|
||||||
|
|
@ -398,6 +398,8 @@ validate_identityref(cxobj *xt,
|
||||||
* in [RFC6241]. If output parameters are returned, they are encoded as
|
* in [RFC6241]. If output parameters are returned, they are encoded as
|
||||||
* child elements to the <rpc-reply> element defined in [RFC6241], in
|
* child elements to the <rpc-reply> element defined in [RFC6241], in
|
||||||
* the same order as they are defined within the "output" statement.
|
* the same order as they are defined within the "output" statement.
|
||||||
|
* @see xml_yang_validate_all
|
||||||
|
* @note Should need a variant accepting cxobj **xret
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_yang_validate_rpc(cxobj *xrpc,
|
xml_yang_validate_rpc(cxobj *xrpc,
|
||||||
|
|
@ -454,6 +456,7 @@ xml_yang_validate_rpc(cxobj *xrpc,
|
||||||
* fail;
|
* fail;
|
||||||
* @endcode
|
* @endcode
|
||||||
* @see xml_yang_validate_all
|
* @see xml_yang_validate_all
|
||||||
|
* @note Should need a variant accepting cxobj **xret
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_yang_validate_add(cxobj *xt,
|
xml_yang_validate_add(cxobj *xt,
|
||||||
|
|
@ -503,15 +506,14 @@ xml_yang_validate_add(cxobj *xt,
|
||||||
* needs to be reparsed when concrete type is selected
|
* needs to be reparsed when concrete type is selected
|
||||||
*/
|
*/
|
||||||
if ((body = xml_body(xt)) != NULL){
|
if ((body = xml_body(xt)) != NULL){
|
||||||
if (cv_parse(body, cv) <0){
|
if (cv_parse1(body, cv, &reason) != 1){
|
||||||
clicon_err(OE_UNIX, errno, "cv_parse");
|
if (netconf_bad_element(cbret, "application", ys->ys_argument, reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((ys_cv_validate(cv, ys, &reason)) != 1){
|
if ((ys_cv_validate(cv, ys, &reason)) != 1){
|
||||||
if (netconf_bad_element(cbret, "application", ys->ys_argument, reason) < 0)
|
if (netconf_bad_element(cbret, "application", ys->ys_argument, reason) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (reason)
|
|
||||||
free(reason);
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -531,6 +533,8 @@ xml_yang_validate_add(cxobj *xt,
|
||||||
done:
|
done:
|
||||||
if (cv)
|
if (cv)
|
||||||
cv_free(cv);
|
cv_free(cv);
|
||||||
|
if (reason)
|
||||||
|
free(reason);
|
||||||
return retval;
|
return retval;
|
||||||
fail:
|
fail:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -544,7 +548,6 @@ xml_yang_validate_add(cxobj *xt,
|
||||||
* @retval 1 Validation OK
|
* @retval 1 Validation OK
|
||||||
* @retval 0 Validation failed
|
* @retval 0 Validation failed
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see xml_yang_validate_add
|
|
||||||
* @code
|
* @code
|
||||||
* cxobj *x;
|
* cxobj *x;
|
||||||
* cbuf *cbret = cbuf_new();
|
* cbuf *cbret = cbuf_new();
|
||||||
|
|
@ -553,6 +556,9 @@ xml_yang_validate_add(cxobj *xt,
|
||||||
* if (ret == 0)
|
* if (ret == 0)
|
||||||
* fail;
|
* fail;
|
||||||
* @endcode
|
* @endcode
|
||||||
|
* @see xml_yang_validate_add
|
||||||
|
* @see xml_yang_validate_rpc
|
||||||
|
* @note Should need a variant accepting cxobj **xret
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml_yang_validate_all(cxobj *xt,
|
xml_yang_validate_all(cxobj *xt,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
# Clixon tests
|
# Clixon tests
|
||||||
|
|
||||||
This directory contains testing code for clixon and the example
|
This directory contains testing code for clixon and the example
|
||||||
routing application. Assumes setup of http daemon as describe under apps/restonf
|
application. Assumes setup of http daemon as describe under apps/restonf
|
||||||
- clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script
|
- clixon A top-level script clones clixon in /tmp and starts all.sh. You can copy this file (review it first) and place as cron script
|
||||||
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically.
|
- all.sh Run through all tests named 'test*.sh' in this directory. Therefore, if you place a test in this directory matching 'test*.sh' it will be run automatically. By default the script will exit on first error. Run as `all.sh summary` to continue and print a summary on all tests.
|
||||||
- test_nacm.sh Auth tests using internal NACM
|
- test_nacm.sh Auth tests using internal NACM
|
||||||
- test_nacm_ext.sh Auth tests using external NACM (separate file)
|
- test_nacm_ext.sh Auth tests using external NACM (separate file)
|
||||||
- test_cli.sh CLI tests
|
- test_cli.sh CLI tests
|
||||||
|
|
@ -13,3 +13,14 @@ routing application. Assumes setup of http daemon as describe under apps/restonf
|
||||||
- test_leafref.sh Yang leafref tests
|
- test_leafref.sh Yang leafref tests
|
||||||
- test_datastore.sh Datastore tests
|
- test_datastore.sh Datastore tests
|
||||||
|
|
||||||
|
Example runs:
|
||||||
|
```
|
||||||
|
> run.sh
|
||||||
|
# Runs through all tests matching 'test_*.sh' in the directory. Prints test output
|
||||||
|
# and stops on first error
|
||||||
|
|
||||||
|
> run.sh summary
|
||||||
|
# Same as above but continues after errors and does not print test output.
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
34
test/all.sh
34
test/all.sh
|
|
@ -1,17 +1,43 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Run, eg as:
|
# Run, eg as:
|
||||||
# ./run.sh 2>&1 | tee test.log
|
# ./all.sh 2>&1 | tee test.log # break on first test
|
||||||
|
# ./all.sh summary # to run all tests and print
|
||||||
|
|
||||||
|
summary=0
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
summary=1
|
||||||
|
fi
|
||||||
|
if [ $# -gt 1 ]; then
|
||||||
|
echo "usage: $0 [summary] # pipe to dev/null and continue on error"
|
||||||
|
exit -1
|
||||||
|
fi
|
||||||
|
|
||||||
# include err() and new() functions
|
# include err() and new() functions
|
||||||
. ./lib.sh
|
. ./lib.sh
|
||||||
|
err=0
|
||||||
for test in test*.sh; do
|
for test in test*.sh; do
|
||||||
echo "Running $test"
|
echo "Running $test"
|
||||||
|
if [ $summary -ne 0 ]; then
|
||||||
|
./$test > /dev/null 2>&1
|
||||||
|
errcode=$?
|
||||||
|
else
|
||||||
./$test
|
./$test
|
||||||
errcode=$?
|
errcode=$?
|
||||||
|
fi
|
||||||
if [ $errcode -ne 0 ]; then
|
if [ $errcode -ne 0 ]; then
|
||||||
echo "Error in $test errcode=$errcode"
|
err=1
|
||||||
|
echo -e "\e[31mError in $test errcode=$errcode"
|
||||||
|
echo -ne "\e[0m"
|
||||||
|
if [ $summary -eq 0 ]; then
|
||||||
exit $errcode
|
exit $errcode
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
echo OK
|
if [ $err -eq 0 ]; then
|
||||||
|
echo OK
|
||||||
|
else
|
||||||
|
echo -e "\e[31mError"
|
||||||
|
echo -ne "\e[0m"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
12
test/lib.sh
12
test/lib.sh
|
|
@ -38,7 +38,9 @@ if [ ! -d $dir ]; then
|
||||||
fi
|
fi
|
||||||
rm -rf $dir/*
|
rm -rf $dir/*
|
||||||
|
|
||||||
# error and exit, arg is optional extra errmsg
|
# error and exit,
|
||||||
|
# arg1: expected
|
||||||
|
# arg2: errmsg[optional]
|
||||||
err(){
|
err(){
|
||||||
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
echo -e "\e[31m\nError in Test$testnr [$testname]:"
|
||||||
if [ $# -gt 0 ]; then
|
if [ $# -gt 0 ]; then
|
||||||
|
|
@ -53,7 +55,7 @@ err(){
|
||||||
echo "$expect"| od -t c > $dir/clixon-expect
|
echo "$expect"| od -t c > $dir/clixon-expect
|
||||||
diff $dir/clixon-expect $dir/clixon-ret
|
diff $dir/clixon-expect $dir/clixon-ret
|
||||||
|
|
||||||
exit $testnr
|
exit -1 #$testnr
|
||||||
}
|
}
|
||||||
|
|
||||||
# Increment test number and print a nice string
|
# Increment test number and print a nice string
|
||||||
|
|
@ -221,8 +223,9 @@ expectwait(){
|
||||||
done
|
done
|
||||||
# cat /tmp/flag
|
# cat /tmp/flag
|
||||||
if [ $(cat /tmp/flag) != "ok" ]; then
|
if [ $(cat /tmp/flag) != "ok" ]; then
|
||||||
cat /tmp/flag
|
# err "ok" $(cat /tmp/flag)
|
||||||
exit
|
# cat /tmp/flag
|
||||||
|
exit -1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,5 +253,4 @@ expectmatch(){
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
new "start restconf daemon (-a is enable basic authentication)"
|
new "start restconf daemon (-a is enable basic authentication)"
|
||||||
sudo su -c "$clixon_restconf -f $cfg -y $fyang -- -a" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG -- -a" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ new "kill old restconf daemon"
|
||||||
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
||||||
|
|
||||||
new "start restconf daemon (-a is enable http basic auth)"
|
new "start restconf daemon (-a is enable http basic auth)"
|
||||||
sudo su -c "$clixon_restconf -f $cfg -y $fyang -- -a" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG -- -a" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
new "start restconf daemon (-a is enable basic authentication)"
|
new "start restconf daemon (-a is enable basic authentication)"
|
||||||
sudo su -c "$clixon_restconf -f $cfg -y $fyang -- -a" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG -- -a" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ new "kill old restconf daemon"
|
||||||
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo su -c "$clixon_restconf -f $cfg -y $fyang" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -282,10 +282,10 @@ new2 "restconf rpc using POST json without mandatory element"
|
||||||
expecteq "$(curl -s -X POST -d '{"input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/ietf-routing:fib-route)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "wrongelement"},"error-severity": "error"}}}
'
|
expecteq "$(curl -s -X POST -d '{"input":{"wrongelement":"ipv4"}}' http://localhost/restconf/operations/ietf-routing:fib-route)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "wrongelement"},"error-severity": "error"}}}
'
|
||||||
|
|
||||||
new2 "restconf rpc non-existing rpc without namespace"
|
new2 "restconf rpc non-existing rpc without namespace"
|
||||||
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang node not found"}}}
'
|
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "missing-element","error-info": {"bad-element": "kalle"},"error-severity": "error","error-message": "RPC not defined"}}}
'
|
||||||
|
|
||||||
new2 "restconf rpc non-existing rpc"
|
new2 "restconf rpc non-existing rpc"
|
||||||
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/example:kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang node not found"}}}
'
|
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations/example:kalle)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "missing-element","error-info": {"bad-element": "kalle"},"error-severity": "error","error-message": "RPC not defined"}}}
'
|
||||||
|
|
||||||
new2 "restconf rpc missing name"
|
new2 "restconf rpc missing name"
|
||||||
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "Operation name expected"}}}
'
|
expecteq "$(curl -s -X POST -d '{}' http://localhost/restconf/operations)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "Operation name expected"}}}
'
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ new "kill old restconf daemon"
|
||||||
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo su -c "$clixon_restconf -f $cfg -y $fyang" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ new "kill old restconf daemon"
|
||||||
sudo pkill -u www-data clixon_restconf
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo su -c "$clixon_restconf -f $cfg" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -D $DBG" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
@ -54,7 +54,7 @@ new "rpc tests"
|
||||||
|
|
||||||
# 1.First some positive tests vary media types
|
# 1.First some positive tests vary media types
|
||||||
#
|
#
|
||||||
new2 "restconf example rpc json/json default - no headers"
|
new2 "restconf example rpc json/json default - no http media headers"
|
||||||
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:example)" '{"output": {"x": "0","y": "42"}}
|
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:example)" '{"output": {"x": "0","y": "42"}}
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|
@ -93,13 +93,13 @@ new2 "restconf add extra"
|
||||||
expecteq "$(curl -s -X POST -d '{"input":{"x":"0","extra":"0"}}' http://localhost/restconf/operations/example:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "extra"},"error-severity": "error"}}}
'
|
expecteq "$(curl -s -X POST -d '{"input":{"x":"0","extra":"0"}}' http://localhost/restconf/operations/example:example)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "unknown-element","error-info": {"bad-element": "extra"},"error-severity": "error"}}}
'
|
||||||
|
|
||||||
new2 "restconf wrong method"
|
new2 "restconf wrong method"
|
||||||
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:wrong)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang node not found"}}}
'
|
expecteq "$(curl -s -X POST -d '{"input":{"x":"0"}}' http://localhost/restconf/operations/example:wrong)" '{"ietf-restconf:errors" : {"error": {"error-type": "application","error-tag": "missing-element","error-info": {"bad-element": "wrong"},"error-severity": "error","error-message": "RPC not defined"}}}
'
|
||||||
|
|
||||||
new2 "restconf edit-config missing mandatory"
|
new2 "restconf edit-config missing mandatory"
|
||||||
expecteq "$(curl -s -X POST -d '{"input":null}' http://localhost/restconf/operations/ietf-netconf:edit-config)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang module not found"}}}
'
|
expecteq "$(curl -s -X POST -d '{"input":null}' http://localhost/restconf/operations/ietf-netconf:edit-config)" '{"ietf-restconf:errors" : {"error": {"error-type": "protocol","error-tag": "operation-failed","error-severity": "error","error-message": "yang module not found"}}}
'
|
||||||
|
|
||||||
new "netconf kill-session missing session-id mandatory"
|
new "netconf kill-session missing session-id mandatory"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><kill-session/></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>session-id</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable</error-message></rpc-error></rpc-reply>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"><kill-session/></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>missing-element</error-tag><error-info><bad-element>session-id</bad-element></error-info><error-severity>error</error-severity><error-message>Mandatory variable</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
# edit-config?
|
# edit-config?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ new "kill old restconf daemon"
|
||||||
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
sudo pkill -u www-data -f "/www-data/clixon_restconf"
|
||||||
|
|
||||||
new "start restconf daemon"
|
new "start restconf daemon"
|
||||||
sudo su -c "$clixon_restconf -f $cfg -y $fyang" -s /bin/sh www-data &
|
sudo su -c "$clixon_restconf -f $cfg -y $fyang -D $DBG" -s /bin/sh www-data &
|
||||||
|
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
|
@ -153,7 +153,7 @@ new "netconf NONEXIST subscription"
|
||||||
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>NONEXIST</stream></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>invalid-value</error-tag><error-severity>error</error-severity><error-message>No such stream</error-message></rpc-error></rpc-reply>]]>]]>$' $NCWAIT
|
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>NONEXIST</stream></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>invalid-value</error-tag><error-severity>error</error-severity><error-message>No such stream</error-message></rpc-error></rpc-reply>]]>]]>$' $NCWAIT
|
||||||
|
|
||||||
new "netconf EXAMPLE subscription with wrong date"
|
new "netconf EXAMPLE subscription with wrong date"
|
||||||
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>EXAMPLE</stream><startTime>kallekaka</startTime></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>startTime</bad-element></error-info><error-severity>error</error-severity><error-message>Expected timestamp</error-message></rpc-error></rpc-reply>]]>]]>$' 0
|
expectwait "$clixon_netconf -qf $cfg -y $fyang" '<rpc><create-subscription><stream>EXAMPLE</stream><startTime>kallekaka</startTime></create-subscription></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>bad-element</error-tag><error-info><bad-element>startTime</bad-element></error-info><error-severity>error</error-severity><error-message>Invalid time: kallekaka</error-message></rpc-error></rpc-reply>]]>]]>$' 0
|
||||||
|
|
||||||
#new "netconf EXAMPLE subscription with replay"
|
#new "netconf EXAMPLE subscription with replay"
|
||||||
#NOW=$(date +"%Y-%m-%dT%H:%M:%S")
|
#NOW=$(date +"%Y-%m-%dT%H:%M:%S")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue