Generic map_str2int generic mapping tables; Removed vector return values from xmldb_get()

This commit is contained in:
Olof hagsand 2017-06-21 21:02:09 +02:00
parent bf30e6f66a
commit abd3eee17d
29 changed files with 381 additions and 280 deletions

View file

@ -219,10 +219,20 @@ from_client_get_config(clicon_handle h,
clicon_err(OE_XML, 0, "db not found");
goto done;
}
if (xmldb_validate_db(db) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", db);
goto ok;
}
if ((xfilter = xml_find(xe, "filter")) != NULL)
if ((selector = xml_find_value(xfilter, "select"))==NULL)
selector="/";
if (xmldb_get(h, db, selector, &xret, NULL, NULL) < 0){
if (xmldb_get(h, db, selector, &xret) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>operation-failed</error-tag>"
"<error-type>application</error-type>"
@ -276,6 +286,16 @@ from_client_edit_config(clicon_handle h,
clicon_err(OE_XML, 0, "db not found");
goto done;
}
if (xmldb_validate_db(target) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", target);
goto ok;
}
/* Check if target locked by other client */
piddb = xmldb_islocked(h, target);
if (piddb && mypid != piddb){
@ -356,6 +376,16 @@ from_client_lock(clicon_handle h,
"</rpc-error></rpc-reply>");
goto ok;
}
if (xmldb_validate_db(db) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", db);
goto ok;
}
/*
* A lock MUST not be granted if either of the following conditions is true:
* 1) A lock is already held by any NETCONF session or another entity.
@ -410,6 +440,15 @@ from_client_unlock(clicon_handle h,
"</rpc-error></rpc-reply>");
goto ok;
}
if (xmldb_validate_db(db) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", db);
goto ok;
}
piddb = xmldb_islocked(h, db);
/*
* An unlock operation will not succeed if any of the following
@ -534,6 +573,16 @@ from_client_copy_config(clicon_handle h,
"</rpc-error></rpc-reply>");
goto ok;
}
if (xmldb_validate_db(source) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", source);
goto ok;
}
if ((target = netconf_db_find(xe, "target")) == NULL){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>missing-element</error-tag>"
@ -543,6 +592,15 @@ from_client_copy_config(clicon_handle h,
"</rpc-error></rpc-reply>");
goto ok;
}
if (xmldb_validate_db(target) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", target);
goto ok;
}
/* Check if target locked by other client */
piddb = xmldb_islocked(h, target);
if (piddb && mypid != piddb){
@ -556,7 +614,6 @@ from_client_copy_config(clicon_handle h,
piddb);
goto ok;
}
if (xmldb_copy(h, source, target) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>operation-failed</error-tag>"
@ -601,6 +658,16 @@ from_client_delete_config(clicon_handle h,
"</rpc-error></rpc-reply>");
goto ok;
}
if (xmldb_validate_db(target) < 0){
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>No such database: %s</error-message>"
"</rpc-error></rpc-reply>", target);
goto ok;
}
/* Check if target locked by other client */
piddb = xmldb_islocked(h, target);
if (piddb && mypid != piddb){

View file

@ -146,9 +146,9 @@ validate_common(clicon_handle h,
goto done;
}
/* 2. Parse xml trees */
if (xmldb_get(h, "running", "/", &td->td_src, NULL, NULL) < 0)
if (xmldb_get(h, "running", "/", &td->td_src) < 0)
goto done;
if (xmldb_get(h, candidate, "/", &td->td_target, NULL, NULL) < 0)
if (xmldb_get(h, candidate, "/", &td->td_target) < 0)
goto done;
/* 3. Compute differences */
@ -212,7 +212,8 @@ validate_common(clicon_handle h,
* The code reverts changes if the commit fails. But if the revert
* fails, we just ignore the errors and proceed. Maybe we should
* do something more drastic?
* @param[in] h Clicon handle
* @param[in] h Clicon handle
* @param[in] candidate A candidate database, not necessarily "candidate"
*/
int
candidate_commit(clicon_handle h,
@ -283,17 +284,17 @@ from_client_commit(clicon_handle h,
piddb);
goto ok;
}
if (candidate_commit(h, "candidate") < 0){
clicon_debug(1, "Commit candidate failed");
/* XXX: candidate_validate should have proper error handling */
cprintf(cbret, "<rpc-reply><rpc-error>"
"<error-tag>missing-attribute</error-tag>"
"<error-tag>invalid-value</error-tag>"
"<error-type>protocol</error-type>"
"<error-severity>error</error-severity>"
"<error-message>%s</error-message>"
"</rpc-error></rpc-reply>",
clicon_err_reason);
goto ok;
goto ok;
}
cprintf(cbret, "<rpc-reply><ok/></rpc-reply>");

View file

@ -212,7 +212,7 @@ done:
static int
candb_reset(clicon_handle h)
{
int retval = -1;
int retval = -1;
if (xmldb_copy(h, "running", "tmp") < 0){
clicon_err(OE_UNIX, errno, "file copy");
@ -590,7 +590,7 @@ main(int argc, char **argv)
*(argv-1) = tmp;
if (reload_running){
/* This could be afailed validation, and we should not fail for that */
/* This could be a failed validation, and we should not fail for that */
(void)candidate_commit(h, "candidate");
}

View file

@ -655,9 +655,9 @@ compare_dbs(clicon_handle h,
astext = cv_int32_get(cvec_i(argv, 0));
else
astext = 0;
if (clicon_rpc_get_config(h, "running", "/", &xc1) < 0)
if (clicon_rpc_get_config(h, "running", "/", 0, &xc1) < 0)
goto done;
if (clicon_rpc_get_config(h, "candidate", "/", &xc2) < 0)
if (clicon_rpc_get_config(h, "candidate", "/", 0, &xc2) < 0)
goto done;
if (compare_xmls(xc1, xc2, astext) < 0) /* astext? */
goto done;
@ -823,7 +823,7 @@ save_config_file(clicon_handle h,
goto done;
}
filename = cv_string_get(cv);
if (clicon_rpc_get_config(h, dbstr,"/", &xt) < 0)
if (clicon_rpc_get_config(h, dbstr,"/", 0, &xt) < 0)
goto done;
if ((f = fopen(filename, "wb")) == NULL){
clicon_err(OE_CFG, errno, "Creating file %s", filename);
@ -1162,7 +1162,7 @@ cli_copy_config(clicon_handle h,
cprintf(cb, xpath, keyname, fromname);
/* Get from object configuration and store in x1 */
if (clicon_rpc_get_config(h, db, cbuf_get(cb), &x1) < 0)
if (clicon_rpc_get_config(h, db, cbuf_get(cb), 0, &x1) < 0)
goto done;
/* Get to variable -> cv -> to name */

View file

@ -657,7 +657,7 @@ clicon_parse(clicon_handle h,
}
res = cliread_parse(cli_cligen(h), cmd, pt, &match_obj, cvv);
if (res != CG_MATCH)
pt_expand_cleanup_1(pt);
pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */
if (msav){
cli_tree_active_set(h, msav);
free(msav);
@ -689,7 +689,7 @@ clicon_parse(clicon_handle h,
}
if ((r = clicon_eval(h, cmd, match_obj, cvv)) < 0)
cli_handler_err(stdout);
pt_expand_cleanup_1(pt);
pt_expand_cleanup_1(pt); /* XXX change to pt_expand_treeref_cleanup */
if (result)
*result = r;
goto done;

View file

@ -140,7 +140,7 @@ expand_dbvar(void *h,
if (api_path_fmt2xpath(api_path, cvv, &xpath) < 0)
goto done;
/* XXX read whole configuration, why not send xpath? */
if (clicon_rpc_get_config(h, dbstr, "/", &xt) < 0)
if (clicon_rpc_get_config(h, dbstr, "/", 0, &xt) < 0)
goto done;
/* One round to detect duplicates
* XXX The code below would benefit from some cleanup
@ -426,7 +426,7 @@ cli_show_config(clicon_handle h,
else
cprintf(cbxpath, "%s", xpath);
/* Get configuration from database */
if (clicon_rpc_get_config(h, db, cbuf_get(cbxpath), &xt) < 0)
if (clicon_rpc_get_config(h, db, cbuf_get(cbxpath), 0, &xt) < 0)
goto done;
/* Print configuration according to format */
switch (format){
@ -505,7 +505,7 @@ show_conf_xpath(clicon_handle h,
}
cv = cvec_find_var(cvv, "xpath");
xpath = cv_string_get(cv);
if (clicon_rpc_get_config(h, str, xpath, &xt) < 0)
if (clicon_rpc_get_config(h, str, xpath, 0, &xt) < 0)
goto done;
if (xpath_vec(xt, xpath, &xv, &xlen) < 0)
goto done;

View file

@ -60,7 +60,7 @@ olof@vandal> curl -G http://127.0.0.1/restconf/data/interfaces/interface/name=et
}
]
curl -sX POST -d '{"clicon":{"interfaces":{"interface":{"name":"eth1","type":"eth","enabled":"true"}}}}' http://localhost/restconf/data
curl -sX POST -d '{"interfaces":{"interface":{"name":"eth1","type":"eth","enabled":"true"}}}' http://localhost/restconf/data
```
### Debugging

View file

@ -156,6 +156,10 @@ api_data_get_gen(clicon_handle h,
cxobj **vec = NULL;
yang_spec *yspec;
cxobj *xret = NULL;
cxobj *xerr;
cbuf *cbj = NULL;;
int code;
char *reason_phrase;
clicon_debug(1, "%s", __FUNCTION__);
yspec = clicon_dbspec_yang(h);
@ -166,16 +170,45 @@ api_data_get_gen(clicon_handle h,
goto done;
}
clicon_debug(1, "%s path:%s", __FUNCTION__, cbuf_get(path));
if (clicon_rpc_get_config(h, "running", cbuf_get(path), &xret) < 0){
if (clicon_rpc_get_config(h, "running", cbuf_get(path), 1, &xret) < 0){
notfound(r);
goto done;
}
#if 0 /* DEBUG */
{
cbuf *cb = cbuf_new();
clicon_xml2cbuf(cb, xret, 0, 0);
xml2json_cbuf(cb, xret, 1);
clicon_debug(1, "%s xret:%s", __FUNCTION__, cbuf_get(cb));
cbuf_free(cb);
}
#endif
if (strcmp(xml_name(xret), "rpc-error") == 0){
if ((cbj = cbuf_new()) == NULL)
goto done;
if ((xerr = xpath_first(xret, "/error-tag")) == NULL){
notfound(r); /* bad reply? */
goto done;
}
code = clicon_str2int(netconf_restconf_map, xml_body(xerr));
if ((reason_phrase = clicon_int2str(http_reason_phrase_map, code)) == NULL)
reason_phrase="";
clicon_debug(1, "%s code:%d reason phrase:%s",
__FUNCTION__, code, reason_phrase);
if (xml_name_set(xret, "error") < 0)
goto done;
if (xml2json_cbuf(cbj, xret, 1) < 0)
goto done;
FCGX_FPrintF(r->out, "Status: %d %s\r\n", code, reason_phrase);
FCGX_FPrintF(r->out, "Content-Type: application/yang-data+json\r\n\r\n");
FCGX_FPrintF(r->out, "\r\n");
FCGX_FPrintF(r->out, "{\r\n");
FCGX_FPrintF(r->out, " \"ietf-restconf:errors\" : {\r\n");
FCGX_FPrintF(r->out, " %s", cbuf_get(cbj));
FCGX_FPrintF(r->out, " }\r\n");
FCGX_FPrintF(r->out, "}\r\n");
goto ok;
}
if ((cbx = cbuf_new()) == NULL)
goto done;
FCGX_SetExitStatus(200, r->out); /* OK */
@ -197,6 +230,8 @@ api_data_get_gen(clicon_handle h,
clicon_debug(1, "%s retval:%d", __FUNCTION__, retval);
if (cbx)
cbuf_free(cbx);
if (cbj)
cbuf_free(cbj);
if (path)
cbuf_free(path);
if (xret)
@ -555,6 +590,7 @@ api_data_delete(clicon_handle h,
goto done;
if ((cbx = cbuf_new()) == NULL)
goto done;
if (clicon_xml2cbuf(cbx, xtop, 0, 0) < 0)
goto done;
if (clicon_rpc_edit_config(h, "candidate",