Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion apps/backend/backend_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,6 @@ from_client_compare(clixon_handle h,
goto done;
goto ok;
}

/* Alt: see dsref handling in rpc_datastore_diff */
if ((db1 = xml_find_body(xe, "source")) == NULL){
if (netconf_missing_element(cbret, "protocol", "source", NULL) < 0)
Expand All @@ -1482,6 +1481,15 @@ from_client_compare(clixon_handle h,
if (netconf_invalid_value(cbret, "protocol", "missing source identifier") < 0)
goto done;
}
/* Do not create a private candidate when comparing */
if (strcmp(id1, "candidate") == 0 && clicon_option_bool(h, "CLICON_XMLDB_PRIVATE_CANDIDATE")) {
if (xmldb_candidate_find(h, "candidate", ce->ce_id, &de1, NULL) < 0)
goto done;
if (de1 == NULL) {
free(id1);
id1 = strdup("running");
}
}
if (xmldb_find_create(h, id1, ce->ce_id, &de1, NULL) < 0)
goto done;
if ((db2 = xml_find_body(xe, "target")) == NULL){
Expand All @@ -1494,8 +1502,18 @@ from_client_compare(clixon_handle h,
if (netconf_invalid_value(cbret, "protocol", "missing target identifier") < 0)
goto done;
}
/* Do not create a private candidate when comparing */
if (strcmp(id2, "candidate") == 0 && clicon_option_bool(h, "CLICON_XMLDB_PRIVATE_CANDIDATE")) {
if (xmldb_candidate_find(h, "candidate", ce->ce_id, &de2, NULL) < 0)
goto done;
if (de2 == NULL) {
free(id2);
id2 = strdup("running");
}
}
if (xmldb_find_create(h, id2, ce->ce_id, &de2, NULL) < 0)
goto done;

/* filter: subtree-filter or xpath-filter */
if ((xpath_filter = xml_find(xe, "xpath-filter")) != NULL){
if ((xpath0 = xml_body(xpath_filter)) != NULL){
Expand Down
46 changes: 35 additions & 11 deletions apps/cli/cli_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,37 @@ compare_db_names(clixon_handle h,
cxobj *xc2 = NULL;
cxobj *xerr = NULL;
cbuf *cb = NULL;
cxobj *xret = NULL;
cxobj *xe;
cxobj *x;
int i;

if (format == FORMAT_XML) { /* new implementation for xml format using rpc compare */
if (clixon_rpc_nmda_compare(h, db1, db2, &xret) < 0) {
clixon_err(OE_PLUGIN, 0, "clixon_rpc_nmda_compare %s %s", db1, db2);
goto done;
}
if (xpath_first(xret, NULL, "//no-matches") != NULL) {
retval = 0;
goto done;
}
if ((cb = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
if ((xe = xpath_first(xret, NULL, "//differences/yang-patch")) == NULL) {
clixon_err(OE_XML, ENOENT, "Expected yang-patch in rpc compare reply");
goto done;
}
cligen_output(stdout, "--- %s\n+++ %s\n", db1, db2);
i = 0;
while ((x = xml_child_iter(xe, &i, -1)) != NULL)
clixon_yangpatch2cbuf(cb, x);
cligen_output(stdout, "%s", cbuf_get(cb));
retval = 0;
goto done;
}
/* xml format handling complete */

if (clicon_rpc_get_config(h, NULL, db1, "/", NULL, NULL, &xc1) < 0)
goto done;
Expand All @@ -866,19 +897,10 @@ compare_db_names(clixon_handle h,
goto done;
goto done;
}
/* Note that XML and TEXT uses a (new) structured in-mem algorithm while
/* Note that TEXT uses a (new) structured in-mem algorithm while
* JSON and CLI uses (old) UNIX file diff.
*/
switch (format){
case FORMAT_XML:
if ((cb = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
goto done;
}
if (clixon_xml_diff2cbuf(cb, xc1, xc2) < 0)
goto done;
cligen_output(stdout, "%s", cbuf_get(cb));
break;
case FORMAT_TEXT:
if ((cb = cbuf_new()) == NULL){
clixon_err(OE_UNIX, errno, "cbuf_new");
Expand All @@ -893,7 +915,7 @@ compare_db_names(clixon_handle h,
if (clixon_compare_xmls(xc1, xc2, format) < 0) /* astext? */
goto done;
default:
break;
goto done;
}
retval = 0;
done:
Expand All @@ -903,6 +925,8 @@ compare_db_names(clixon_handle h,
xml_free(xc1);
if (xc2)
xml_free(xc2);
if (xret)
xml_free(xret);
return retval;
}

Expand Down
4 changes: 4 additions & 0 deletions lib/clixon/clixon_netconf_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@
*/
#define NETCONF_COMPARE_NAMESPACE "urn:ietf:params:xml:ns:yang:ietf-nmda-compare"

/* RFC 8342: Network Management Datastore Architecture (NMDA)
*/
#define NETCONF_DATASTORES_NAMESPACE "urn:ietf:params:xml:ns:yang:ietf-datastores"

/*! draft-ietf-netconf-privcand NETCONF and RESTCONF Private Candidate Datastores
*/
#define NETCONF_PRIVCAND_NAMESPACE "urn:ietf:params:xml:ns:yang:ietf-netconf-private-candidate"
Expand Down
1 change: 1 addition & 0 deletions lib/clixon/clixon_proto_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ int clixon_rpc_api_path2xml(clixon_handle h, const char *api_path, const char *b
int clixon_rpc_translate_format(clixon_handle h, enum format_enum format, const char *xpath, cvec *nsc,
cxobj *xt, int pretty, int skiptop, int cli_aware, const char *prepend, cbuf *cb);
int clicon_rpc_restart_plugin(clixon_handle h, const char *plugin);
int clixon_rpc_nmda_compare(clixon_handle h, const char *db1, const char *db2, cxobj **xt);

/*-- Backward compatible 7.6 --*/
static inline int
Expand Down
2 changes: 1 addition & 1 deletion lib/clixon/clixon_xml_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ int clixon_xml_parse_string1(clixon_handle h, const char *str, yang_bind yb, y
int clixon_xml_parse_va(yang_bind yb, yang_stmt *yspec, cxobj **xt, cxobj **xerr,
const char *format, ...) __attribute__ ((format (printf, 5, 6)));
int clixon_xml_attr_copy(cxobj *xin, cxobj *xout, const char *name);
int clixon_xml_diff2cbuf(cbuf *cb, cxobj *x0, cxobj *x1);
int clixon_yangpatch2cbuf(cbuf *cb, cxobj *xe);

static inline int
clixon_xml2cbuf(cbuf *cb,
Expand Down
61 changes: 61 additions & 0 deletions lib/src/clixon_proto_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2495,3 +2495,64 @@ clixon_rpc_nacm_autocli_filter(clixon_handle h,
xml_free(xret);
return retval;
}

/* Make a clixon compare call from client to backend server
*
* @param[in] h Clixon handle
* @param[in] db1 Source datastore
* @param[in] db2 Target datastore
* @param[out] xt Pointer to roc reply to be freed by caller, or NULL
* @retval 0 rpc reply ok
* @retval -1 Error
*/

int
clixon_rpc_nmda_compare(clixon_handle h,
const char *db1,
const char *db2,
cxobj **xt)
{
int retval = -1;
cbuf *cb = NULL;
cxobj *xret = NULL;
char *username;
uint32_t session_id;

clixon_debug(CLIXON_DBG_DEFAULT | CLIXON_DBG_DETAIL, "db1: %s, db2: %s", db1, db2);
if (session_id_check(h, &session_id) < 0)
goto done;
if ((cb = cbuf_new()) == NULL){
clixon_err(OE_XML, errno, "cbuf_new");
goto done;
}
cprintf(cb, "<rpc xmlns=\"%s\"", NETCONF_BASE_NAMESPACE);
cprintf(cb, " xmlns:%s=\"%s\"", NETCONF_BASE_PREFIX, NETCONF_BASE_NAMESPACE);
if ((username = clicon_username_get(h)) != NULL){
cprintf(cb, " %s:username=\"%s\"", CLIXON_LIB_PREFIX, username);
cprintf(cb, " xmlns:%s=\"%s\"", CLIXON_LIB_PREFIX, CLIXON_LIB_NS);
}
cprintf(cb, " message-id=\"%d\">", netconf_message_id_next(h));
cprintf(cb, "<compare xmlns=\"%s\" xmlns:ds=\"%s\">",
NETCONF_COMPARE_NAMESPACE, NETCONF_DATASTORES_NAMESPACE);
cprintf(cb, "<source>ds:%s</source>", db1);
cprintf(cb, "<target>ds:%s</target>", db2);
cprintf(cb, "</compare></rpc>");
if (clicon_rpc_msg(h, cb, &xret) < 0)
goto done;

if ((xpath_first(xret, NULL, "//rpc-error")) != NULL){
clixon_err_netconf(h, OE_NETCONF, 0, xret, "compare rpc error");
goto done;
}
*xt = xret;
xret = NULL;
retval = 0;
done:
clixon_debug(CLIXON_DBG_DEFAULT | CLIXON_DBG_DETAIL, "retval:%d", retval);
if (cb)
cbuf_free(cb);
if (xret)
xml_free(xret);
return retval;
}

7 changes: 1 addition & 6 deletions lib/src/clixon_text_syntax.c
Original file line number Diff line number Diff line change
Expand Up @@ -741,8 +741,6 @@ text_diff_keys(cbuf *cb,
* @param[in] skiptop 0: Include top object 1: Skip top-object, only children,
* @retval 0 Ok
* @retval -1 Error
* @see xml_diff_ordered_by_user
* @see text_diff2cbuf_ordered_by_user
*/
static int
text_diff2cbuf_ordered_by_user(cbuf *cb,
Expand Down Expand Up @@ -814,7 +812,7 @@ text_diff2cbuf_ordered_by_user(cbuf *cb,
* if (clixon_text_diff2cbuf(cb, 0, x0, x1, 0) < 0)
* err();
* @endcode
* @see clixon_xml_diff2cbuf

* XXX Leaf-list +/- is not correct
* For example, it should be:
* value [
Expand All @@ -826,9 +824,7 @@ text_diff2cbuf_ordered_by_user(cbuf *cb,
* + 97
* - 99
* @see clixon_compare_xmls which uses files and is independent of YANG
* @see xml_diff2cbuf for XML
* @see xml_tree_equal Equal or not
* @see xml_diff Diff sets
*/
static int
text_diff2cbuf(cbuf *cb,
Expand Down Expand Up @@ -1095,7 +1091,6 @@ text_diff2cbuf(cbuf *cb,
* if (clixon_text_diff2cbuf(cb, 0, x0, x1) < 0)
* err();
* @endcode
* @see clixon_xml_diff2cbuf
*/
int
clixon_text_diff2cbuf(cbuf *cb,
Expand Down
15 changes: 11 additions & 4 deletions lib/src/clixon_xml_diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1783,18 +1783,24 @@ clixon_xml_diff2patch(cxobj *x1,
{
int retval = -1;
int nr = 1;
uint16_t f1 = 0;
uint16_t f2 = 0;

if (x1)
if (x1) {
f1 = xml_flag(x1, XML_FLAG_TOP);
xml_flag_set(x1, XML_FLAG_TOP);
if (x2)
}
if (x2) {
f2 = xml_flag(x2, XML_FLAG_TOP);
xml_flag_set(x2, XML_FLAG_TOP);
}
if (xml_diff2patch(x1, x2, flags, xpatch, &nr) < 0)
goto done;
retval = 0;
done:
if (x1)
if (x1 && !f1)
xml_flag_reset(x1, XML_FLAG_TOP);
if (x2)
if (x2 && !f2)
xml_flag_reset(x2, XML_FLAG_TOP);
return retval;
}
Expand Down Expand Up @@ -1830,3 +1836,4 @@ clixon_xml_diff_nacm_read(clixon_handle h,
done:
return retval;
}

Loading