diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d23695a..308c0786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,11 @@ Expected: July 2020 ### C/CLI-API changes on existing features (For developers) +* Changed module-specific upgrade API, not backward compatible. The API has been simplified which means more has to be done by the programmer. + * In summary, a user registers an upgrade callback per module. The callback is called at startup if the module is added, has been removed or if the revision on file is different from the one in the system. + * The register function has removed `from` and `rev` parameters: `upgrade_callback_register(h, cb, namespace, arg)` + * The callback function has a new `op` parameter with possible values: `XML_FLAG_ADD`, `XML_FLAG_CHANGE` or `XML_FLAG_CHANGE`: `clicon_upgrade_cb(h, xn, ns, op, from, to, arg, cbret)` + * Added new cli show functions to work with cligen_output for cligen pageing to work. To achieve this, replace function calls as follows: * xml2txt(...) --> xml2txt_cb(..., cligen_output) * xml2cli(...) --> xml2cli_cb(..., cligen_output) diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 823eb878..f1e16882 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -177,19 +177,19 @@ startup_common(clicon_handle h, int retval = -1; yang_stmt *yspec; int ret; - modstate_diff_t *msd = NULL; + modstate_diff_t *msdiff = NULL; cxobj *xt = NULL; cxobj *x; cxobj *xret = NULL; /* If CLICON_XMLDB_MODSTATE is enabled, then get the db XML with - * potentially non-matching module-state in msd + * potentially non-matching module-state in msdiff */ if (clicon_option_bool(h, "CLICON_XMLDB_MODSTATE")) - if ((msd = modstate_diff_new()) == NULL) + if ((msdiff = modstate_diff_new()) == NULL) goto done; clicon_debug(1, "Reading startup config from %s", db); - if (xmldb_get0(h, db, NULL, "/", 0, &xt, msd) < 0) + if (xmldb_get0(h, db, NULL, "/", 0, &xt, msdiff) < 0) goto done; clicon_debug(1, "Reading startup config done"); /* Clear flags xpath for get */ @@ -202,13 +202,15 @@ startup_common(clicon_handle h, } /* Here xt is old syntax */ /* General purpose datastore upgrade */ - if (clixon_plugin_datastore_upgrade_all(h, db, xt, msd) < 0) + if (clixon_plugin_datastore_upgrade_all(h, db, xt, msdiff) < 0) goto done; /* Module-specific upgrade callbacks */ - if ((ret = clixon_module_upgrade(h, xt, msd, cbret)) < 0) - goto done; - if (ret == 0) - goto fail; + if (msdiff){ + if ((ret = clixon_module_upgrade(h, xt, msdiff, cbret)) < 0) + goto done; + if (ret == 0) + goto fail; + } if ((yspec = clicon_dbspec_yang(h)) == NULL){ clicon_err(OE_YANG, 0, "Yang spec not set"); goto done; @@ -257,8 +259,8 @@ startup_common(clicon_handle h, xml_free(xret); if (xt) xml_free(xt); - if (msd) - modstate_diff_free(msd); + if (msdiff) + modstate_diff_free(msdiff); return retval; fail: retval = 0; diff --git a/example/main/example_backend.c b/example/main/example_backend.c index 7996fb53..86d78ebc 100644 --- a/example/main/example_backend.c +++ b/example/main/example_backend.c @@ -535,9 +535,9 @@ static const map_str2str namespace_map[] = { */ int example_upgrade(clicon_handle h, - char *db, - cxobj *xt, - modstate_diff_t *msd) + char *db, + cxobj *xt, + modstate_diff_t *msd) { int retval = -1; cvec *nsc = NULL; /* Canonical namespace */ @@ -616,16 +616,17 @@ example_upgrade(clicon_handle h, * @param[in] h Clicon handle * @param[in] xn XML tree to be updated * @param[in] ns Namespace of module (for info) + * @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE * @param[in] from From revision on the form YYYYMMDD * @param[in] to To revision on the form YYYYMMDD (0 not in system) * @param[in] arg User argument given at rpc_callback_register() - * @param[out] cbret Return xml tree, eg ..., ..., ..., ..., ..., ..., ..., add to list mark as DEL * 3b) File module-state matches system - * 3c) File module-state does not match system + * 3c) File module-state does not match system -> add to list mark as CHANGE + * 4) For each module state s in the system + * 4a) If there is no such module in the file -> add to list mark as ADD */ static int text_read_modstate(clicon_handle h, yang_stmt *yspec, cxobj *xt, - modstate_diff_t *msd) + modstate_diff_t *msdiff) { int retval = -1; - cxobj *xmodst; - cxobj *xm = NULL; - cxobj *xm2; - cxobj *xs; - char *name; /* module name */ - char *mrev; /* file revision */ - char *srev; /* system revision */ - cxobj *xmcache = NULL; + cxobj *xmodfile = NULL; /* modstate of system (loaded yang modules in runtime) */ + cxobj *xmodsystem = NULL; /* modstate of file, eg startup */ + cxobj *xf = NULL; /* xml modstate in file */ + cxobj *xf2; /* copy */ + cxobj *xs; /* xml modstate in system */ + cxobj *xs2; /* copy */ + char *name; /* module name */ + char *frev; /* file revision */ + char *srev; /* system revision */ - xmcache = clicon_modst_cache_get(h, 1); - if ((xmodst = xml_find_type(xt, NULL, "modules-state", CX_ELMNT)) == NULL){ + /* Read module-state as computed at startup, see startup_module_state() */ + xmodsystem = clicon_modst_cache_get(h, 1); + if ((xmodfile = xml_find_type(xt, NULL, "modules-state", CX_ELMNT)) == NULL){ /* 1) There is no modules-state info in the file */ } - else if (xmcache && msd){ - msd->md_status = 1; /* There is module state in the file */ - /* Create diff trees */ + else if (xmodsystem && msdiff){ + msdiff->md_status = 1; /* There is module state in the file */ + /* Create modstate tree for this file */ if (clixon_xml_parse_string("", - YB_MODULE, yspec, &msd->md_del, NULL) < 0) + YB_MODULE, yspec, &msdiff->md_diff, NULL) < 0) goto done; - if (xml_rootchild(msd->md_del, 0, &msd->md_del) < 0) - goto done; - if (clixon_xml_parse_string("", - YB_MODULE, yspec, &msd->md_mod, NULL) < 0) - goto done; - if (xml_rootchild(msd->md_mod, 0, &msd->md_mod) < 0) + if (xml_rootchild(msdiff->md_diff, 0, &msdiff->md_diff) < 0) goto done; /* 3) For each module state m in the file */ - while ((xm = xml_child_each(xmodst, xm, CX_ELMNT)) != NULL) { - if (strcmp(xml_name(xm), "module-set-id") == 0){ - if (xml_body(xm) && (msd->md_set_id = strdup(xml_body(xm))) == NULL){ + xf = NULL; + while ((xf = xml_child_each(xmodfile, xf, CX_ELMNT)) != NULL) { + if (strcmp(xml_name(xf), "module-set-id") == 0){ + if (xml_body(xf) && (msdiff->md_set_id = strdup(xml_body(xf))) == NULL){ clicon_err(OE_UNIX, errno, "strdup"); goto done; } } - if (strcmp(xml_name(xm), "module")) + if (strcmp(xml_name(xf), "module")) continue; /* ignore other tags, such as module-set-id */ - if ((name = xml_find_body(xm, "name")) == NULL) + if ((name = xml_find_body(xf, "name")) == NULL) continue; /* 3a) There is no such module in the system */ - if ((xs = xpath_first(xmcache, NULL, "module[name=\"%s\"]", name)) == NULL){ - // fprintf(stderr, "%s: Module %s: not in system\n", __FUNCTION__, name); - if ((xm2 = xml_dup(xm)) == NULL) + if ((xs = xpath_first(xmodsystem, NULL, "module[name=\"%s\"]", name)) == NULL){ + if ((xf2 = xml_dup(xf)) == NULL) /* Make a copy of this modstate */ goto done; - if (xml_addsub(msd->md_del, xm2) < 0) + if (xml_addsub(msdiff->md_diff, xf2) < 0) /* Add it to modstatediff */ goto done; + xml_flag_set(xf2, XML_FLAG_DEL); continue; } /* These two shouldnt happen since revision is key, just ignore */ - if ((mrev = xml_find_body(xm, "revision")) == NULL) + if ((frev = xml_find_body(xf, "revision")) == NULL) continue; if ((srev = xml_find_body(xs, "revision")) == NULL) continue; - if (strcmp(mrev, srev)==0){ - /* 3b) File module-state matches system */ - // fprintf(stderr, "%s: Module %s: file \"%s\" and system revisions match\n", __FUNCTION__, name, mrev); - } - else{ + if (strcmp(frev, srev)!=0){ /* 3c) File module-state does not match system */ - // fprintf(stderr, "%s: Module %s: file \"%s\" and system \"%s\" revisions do not match\n", __FUNCTION__, name, mrev, srev); - if ((xm2 = xml_dup(xm)) == NULL) + if ((xf2 = xml_dup(xf)) == NULL) goto done; - if (xml_addsub(msd->md_mod, xm2) < 0) + if (xml_addsub(msdiff->md_diff, xf2) < 0) goto done; + xml_flag_set(xf2, XML_FLAG_CHANGE); + } + } + /* 4) For each module state s in the system (xmodsystem) */ + xs = NULL; + while ((xs = xml_child_each(xmodsystem, xs, CX_ELMNT)) != NULL) { + if (strcmp(xml_name(xs), "module")) + continue; /* ignore other tags, such as module-set-id */ + if ((name = xml_find_body(xs, "name")) == NULL) + continue; + /* 4a) If there is no such module in the file -> add to list mark as ADD */ + if ((xf = xpath_first(xmodfile, NULL, "module[name=\"%s\"]", name)) == NULL){ + if ((xs2 = xml_dup(xs)) == NULL) /* Make a copy of this modstate */ + goto done; + if (xml_addsub(msdiff->md_diff, xs2) < 0) /* Add it to modstatediff */ + goto done; + xml_flag_set(xs2, XML_FLAG_ADD); + continue; } } } @@ -305,8 +324,8 @@ text_read_modstate(clicon_handle h, * in all cases, whether CLICON_XMLDB_MODSTATE is on or not. * Clixon systems with CLICON_XMLDB_MODSTATE disabled ignores it */ - if (xmodst){ - if (xml_purge(xmodst) < 0) + if (xmodfile){ + if (xml_purge(xmodfile) < 0) goto done; } retval = 0; @@ -319,14 +338,14 @@ text_read_modstate(clicon_handle h, * @param[in] db Symbolic database name, eg "candidate", "running" * @param[in] yspec Top-level yang spec * @param[out] xp XML tree read from file - * @param[out] msd If set, return modules-state differences + * @param[out] msdiff If set, return modules-state differences */ int xmldb_readfile(clicon_handle h, const char *db, yang_stmt *yspec, cxobj **xp, - modstate_diff_t *msd) + modstate_diff_t *msdiff) { int retval = -1; cxobj *x0 = NULL; @@ -373,7 +392,7 @@ xmldb_readfile(clicon_handle h, /* From Clixon 3.10,datastore files may contain module-state defining * which modules are used in the file. */ - if (text_read_modstate(h, yspec, x0, msd) < 0) + if (text_read_modstate(h, yspec, x0, msdiff) < 0) goto done; if (xp){ *xp = x0; @@ -399,7 +418,7 @@ xmldb_readfile(clicon_handle h, * @param[in] nsc External XML namespace context, or NULL * @param[in] xpath String with XPATH syntax. or NULL for all * @param[out] xret Single return XML tree. Free with xml_free() - * @param[out] msd If set, return modules-state differences + * @param[out] msdiff If set, return modules-state differences * @retval 0 OK * @retval -1 Error * @see xmldb_get the generic API function @@ -410,7 +429,7 @@ xmldb_get_nocache(clicon_handle h, cvec *nsc, char *xpath, cxobj **xtop, - modstate_diff_t *msd) + modstate_diff_t *msdiff) { int retval = -1; char *dbfile = NULL; @@ -426,7 +445,7 @@ xmldb_get_nocache(clicon_handle h, clicon_err(OE_YANG, ENOENT, "No yang spec"); goto done; } - if (xmldb_readfile(h, db, yspec, &xt, msd) < 0) + if (xmldb_readfile(h, db, yspec, &xt, msdiff) < 0) goto done; /* Here xt looks like: ... */ /* Given the xpath, return a vector of matches in xvec */ @@ -483,7 +502,7 @@ xmldb_get_nocache(clicon_handle h, * @param[in] nsc External XML namespace context, or NULL * @param[in] xpath String with XPATH syntax. or NULL for all * @param[out] xret Single return XML tree. Free with xml_free() - * @param[out] msd If set, return modules-state differences + * @param[out] msdiff If set, return modules-state differences * @retval 0 OK * @retval -1 Error * @see xmldb_get the generic API function @@ -494,7 +513,7 @@ xmldb_get_cache(clicon_handle h, cvec *nsc, char *xpath, cxobj **xtop, - modstate_diff_t *msd) + modstate_diff_t *msdiff) { int retval = -1; yang_stmt *yspec; @@ -514,7 +533,7 @@ xmldb_get_cache(clicon_handle h, de = clicon_db_elmnt_get(h, db); if (de == NULL || de->de_xml == NULL){ /* Cache miss, read XML from file */ /* If there is no xml x0 tree (in cache), then read it from file */ - if (xmldb_readfile(h, db, yspec, &x0t, msd) < 0) + if (xmldb_readfile(h, db, yspec, &x0t, msdiff) < 0) goto done; /* XXX: should we validate file if read from disk? * Argument against: we may want to have a semantically wrong file and wish @@ -585,7 +604,7 @@ xmldb_get_cache(clicon_handle h, * @param[in] xpath String with XPATH syntax. or NULL for all * @param[in] config If set only configuration data, else also state * @param[out] xret Single return XML tree. Free with xml_free() - * @param[out] msd If set, return modules-state differences + * @param[out] msdiff If set, return modules-state differences * @retval 0 OK * @retval -1 Error */ @@ -595,7 +614,7 @@ xmldb_get_zerocopy(clicon_handle h, cvec *nsc, char *xpath, cxobj **xtop, - modstate_diff_t *msd) + modstate_diff_t *msdiff) { int retval = -1; yang_stmt *yspec; @@ -614,7 +633,7 @@ xmldb_get_zerocopy(clicon_handle h, de = clicon_db_elmnt_get(h, db); if (de == NULL || de->de_xml == NULL){ /* Cache miss, read XML from file */ /* If there is no xml x0 tree (in cache), then read it from file */ - if (xmldb_readfile(h, db, yspec, &x0t, msd) < 0) + if (xmldb_readfile(h, db, yspec, &x0t, msdiff) < 0) goto done; /* XXX: should we validate file if read from disk? * Argument against: we may want to have a semantically wrong file and wish @@ -689,7 +708,7 @@ xmldb_get(clicon_handle h, * @param[in] xpath String with XPATH syntax. or NULL for all * @param[in] copy Force copy. Overrides cache_zerocopy -> cache * @param[out] xret Single return XML tree. Free with xml_free() - * @param[out] msd If set, return modules-state differences (upgrade code) + * @param[out] msdiff If set, return modules-state differences (upgrade code) * @retval 0 OK * @retval -1 Error * @code @@ -710,7 +729,7 @@ xmldb_get0(clicon_handle h, char *xpath, int copy, cxobj **xret, - modstate_diff_t *msd) + modstate_diff_t *msdiff) { int retval = -1; @@ -720,7 +739,7 @@ xmldb_get0(clicon_handle h, * Add default values in copy * Copy deleted by xmldb_free */ - retval = xmldb_get_nocache(h, db, nsc, xpath, xret, msd); + retval = xmldb_get_nocache(h, db, nsc, xpath, xret, msdiff); break; case DATASTORE_CACHE_ZEROCOPY: /* Get cache (file if empty) mark xpath match in original tree @@ -728,7 +747,7 @@ xmldb_get0(clicon_handle h, * Default values and markings removed in xmldb_clear */ if (!copy){ - retval = xmldb_get_zerocopy(h, db, nsc, xpath, xret, msd); + retval = xmldb_get_zerocopy(h, db, nsc, xpath, xret, msdiff); break; } /* fall through */ @@ -737,7 +756,7 @@ xmldb_get0(clicon_handle h, * Add default values in copy, return copy * Copy deleted by xmldb_free */ - retval = xmldb_get_cache(h, db, nsc, xpath, xret, msd); + retval = xmldb_get_cache(h, db, nsc, xpath, xret, msdiff); break; } return retval; diff --git a/lib/src/clixon_plugin.c b/lib/src/clixon_plugin.c index f38383e4..d34e3195 100644 --- a/lib/src/clixon_plugin.c +++ b/lib/src/clixon_plugin.c @@ -793,9 +793,6 @@ typedef struct { const char *uc_fnstr; /* Stringified fn name for debug */ void *uc_arg; /* Application specific argument to cb */ char *uc_namespace; /* Module namespace */ - uint32_t uc_rev; /* Module revision (to) in YYYYMMDD format or 0 */ - uint32_t uc_from; /* Module revision (from) or 0 in YYYYMMDD format */ - } upgrade_callback_t; /* List of rpc callback entries XXX hang on handle */ @@ -808,8 +805,6 @@ static upgrade_callback_t *upgrade_cb_list = NULL; * @param[in] fnstr Stringified function for debug * @param[in] arg Domain-specific argument to send to callback * @param[in] namespace Module namespace (if NULL all modules) - * @param[in] from From module revision (0 from any revision) - * @param[in] revision To module revision (0 means module obsoleted) * @retval 0 OK * @retval -1 Error * @see upgrade_callback_call which makes the actual callback @@ -819,8 +814,6 @@ upgrade_callback_reg_fn(clicon_handle h, clicon_upgrade_cb cb, const char *fnstr, char *namespace, - uint32_t from, - uint32_t revision, void *arg) { upgrade_callback_t *uc; @@ -835,8 +828,6 @@ upgrade_callback_reg_fn(clicon_handle h, uc->uc_arg = arg; if (namespace) uc->uc_namespace = strdup(namespace); - uc->uc_rev = revision; - uc->uc_from = from; ADDQ(uc, upgrade_cb_list); return 0; done: @@ -864,14 +855,14 @@ upgrade_callback_delete_all(clicon_handle h) return 0; } -/*! Search Upgrade callbacks and invoke if module match +/*! Upgrade specific module identified by namespace, search matching callbacks * * @param[in] h clicon handle * @param[in] xt Top-level XML tree to be updated (includes other ns as well) - * @param[in] modname Name of module - * @param[in] modns Namespace of module (for info) - * @param[in] from From revision on the form YYYYMMDD - * @param[in] to To revision on the form YYYYMMDD (0 not in system) + * @param[in] ns Namespace of module + * @param[in] op One of XML_FLAG_ADD, _DEL or _CHANGE + * @param[in] from From revision on the form YYYYMMDD (if DEL or CHANGE) + * @param[in] to To revision on the form YYYYMMDD (if ADD or CHANGE) * @param[out] cbret Return XML (as string in CLIgen buffer), on invalid * @retval -1 Error * @retval 0 Invalid - cbret contains reason as netconf @@ -881,7 +872,8 @@ upgrade_callback_delete_all(clicon_handle h) int upgrade_callback_call(clicon_handle h, cxobj *xt, - char *namespace, + char *ns, + uint16_t op, uint32_t from, uint32_t to, cbuf *cbret) @@ -903,23 +895,21 @@ upgrade_callback_call(clicon_handle h, * - Registered from revision >= from AND * - Registered to revision <= to (which includes case both 0) */ - if (uc->uc_namespace == NULL || strcmp(uc->uc_namespace, namespace)==0) - if ((uc->uc_from == 0) || - (uc->uc_from >= from && uc->uc_rev <= to)){ - if ((ret = uc->uc_callback(h, xt, namespace, from, to, uc->uc_arg, cbret)) < 0){ - clicon_debug(1, "%s Error in: %s", __FUNCTION__, uc->uc_namespace); + if (uc->uc_namespace == NULL || strcmp(uc->uc_namespace, ns)==0){ + if ((ret = uc->uc_callback(h, xt, ns, op, from, to, uc->uc_arg, cbret)) < 0){ + clicon_debug(1, "%s Error in: %s", __FUNCTION__, uc->uc_namespace); + goto done; + } + if (ret == 0){ + if (cbuf_len(cbret)==0){ + clicon_err(OE_CFG, 0, "Validation fail %s(%s): cbret not set", + uc->uc_fnstr, ns); goto done; } - if (ret == 0){ - if (cbuf_len(cbret)==0){ - clicon_err(OE_CFG, 0, "Validation fail %s(%s): cbret not set", - uc->uc_fnstr, namespace); - goto done; - } - goto fail; - } - nr++; + goto fail; } + nr++; + } uc = NEXTQ(upgrade_callback_t *, uc); } while (uc != upgrade_cb_list); retval = 1; diff --git a/lib/src/clixon_xml_changelog.c b/lib/src/clixon_xml_changelog.c index 2336cd87..02bef24e 100644 --- a/lib/src/clixon_xml_changelog.c +++ b/lib/src/clixon_xml_changelog.c @@ -356,6 +356,7 @@ changelog_iterate(clicon_handle h, * @param[in] h Clicon handle * @param[in] xt Top-level XML tree to be updated (includes other ns as well) * @param[in] namespace Namespace of module (for info) + * @param[in] op One of XML_FLAG_ADD, _DEL, _CHANGE * @param[in] from From revision on the form YYYYMMDD * @param[in] to To revision on the form YYYYMMDD (0 not in system) * @param[in] arg User argument given at rpc_callback_register() @@ -367,12 +368,13 @@ changelog_iterate(clicon_handle h, */ int xml_changelog_upgrade(clicon_handle h, - cxobj *xt, - char *namespace, - uint32_t from, - uint32_t to, - void *arg, - cbuf *cbret) + cxobj *xt, + char *namespace, + uint16_t op, + uint32_t from, + uint32_t to, + void *arg, + cbuf *cbret) { int retval = -1; cxobj *xchlog; /* changelog */ diff --git a/lib/src/clixon_yang_module.c b/lib/src/clixon_yang_module.c index d3a8c030..38632e48 100644 --- a/lib/src/clixon_yang_module.c +++ b/lib/src/clixon_yang_module.c @@ -101,10 +101,8 @@ modstate_diff_free(modstate_diff_t *md) return 0; if (md->md_set_id) free(md->md_set_id); - if (md->md_del) - xml_free(md->md_del); - if (md->md_mod) - xml_free(md->md_mod); + if (md->md_diff) + xml_free(md->md_diff); free(md); return 0; } @@ -375,13 +373,13 @@ yang_modules_state_get(clicon_handle h, /*! For single module state with namespace, get revisions and send upgrade callbacks * @param[in] h Clicon handle - * @param[in] xt Top-level XML tree to be updated (includes other ns as well) - * @param[in] xs XML module state (for one yang module) + * @param[in] xt Top-level XML tree to be updated (includes other ns as well) + * @param[in] xd XML module state diff (for one yang module) * @param[in] xvec Help vector where to store XML child nodes (??) * @param[in] xlen Length of xvec * @param[in] ns0 Namespace of module state we are looking for - * @param[in] deleted If set, dont look for system yang module and "to" rev - * @param[out] cbret Netconf error message if invalid + * @param[in] op add,del, or mod + * @param[out] cbret Netconf error message if invalid * @retval 1 OK * @retval 0 Validation failed (cbret set) * @retval -1 Error @@ -389,9 +387,8 @@ yang_modules_state_get(clicon_handle h, static int mod_ns_upgrade(clicon_handle h, cxobj *xt, - cxobj *xs, + cxobj *xmod, char *ns, - int deleted, cbuf *cbret) { int retval = -1; @@ -403,15 +400,14 @@ mod_ns_upgrade(clicon_handle h, int ret; yang_stmt *yspec; - /* Make upgrade callback for this XML, specifying the module - * namespace, from and to revision. - */ - if ((b = xml_find_body(xs, "revision")) != NULL) /* Module revision */ - if (ys_parse_date_arg(b, &from) < 0) - goto done; - if (deleted) - to = 0; - else { /* Look up system module (alt send it via argument) */ + /* If modified or removed get from revision from file */ + if (xml_flag(xmod, (XML_FLAG_CHANGE|XML_FLAG_DEL)) != 0x0){ + if ((b = xml_find_body(xmod, "revision")) != NULL) /* Module revision */ + if (ys_parse_date_arg(b, &from) < 0) + goto done; + } + /* If modified or added get to revision from system */ + if (xml_flag(xmod, (XML_FLAG_CHANGE|XML_FLAG_ADD)) != 0x0){ yspec = clicon_dbspec_yang(h); if ((ymod = yang_find_module_by_namespace(yspec, ns)) == NULL) goto fail; @@ -420,7 +416,9 @@ mod_ns_upgrade(clicon_handle h, if (ys_parse_date_arg(yang_argument_get(yrev), &to) < 0) goto done; } - if ((ret = upgrade_callback_call(h, xt, ns, from, to, cbret)) < 0) + if ((ret = upgrade_callback_call(h, xt, ns, + xml_flag(xmod, (XML_FLAG_CHANGE|XML_FLAG_ADD|XML_FLAG_CHANGE)), + from, to, cbret)) < 0) goto done; if (ret == 0) /* XXX ignore and continue? */ goto fail; @@ -447,33 +445,25 @@ clixon_module_upgrade(clicon_handle h, modstate_diff_t *msd, cbuf *cbret) { - int retval = -1; - char *ns; /* Namespace */ - cxobj *xs; /* XML module state */ - int ret; + int retval = -1; + char *ns; /* Namespace */ + cxobj *xmod; /* XML module state diff */ + int ret; - if (msd == NULL) + if (msd == NULL){ + clicon_err(OE_CFG, EINVAL, "No modstate"); + goto done; + } + if (msd->md_status == 0) /* No modstate in startup */ goto ok; /* Iterate through xml modified module state */ - xs = NULL; - while ((xs = xml_child_each(msd->md_mod, xs, CX_ELMNT)) != NULL) { + xmod = NULL; + while ((xmod = xml_child_each(msd->md_diff, xmod, CX_ELMNT)) != NULL) { /* Extract namespace */ - if ((ns = xml_find_body(xs, "namespace")) == NULL) + if ((ns = xml_find_body(xmod, "namespace")) == NULL) goto done; /* Extract revisions and make callbacks */ - if ((ret = mod_ns_upgrade(h, xt, xs, ns, 0, cbret)) < 0) - goto done; - if (ret == 0) - goto fail; - } - /* Iterate through xml deleted module state */ - xs = NULL; - while ((xs = xml_child_each(msd->md_del, xs, CX_ELMNT)) != NULL) { - /* Extract namespace */ - if ((ns = xml_find_body(xs, "namespace")) == NULL) - continue; - /* Extract revisions and make callbacks (now w deleted=1) */ - if ((ret = mod_ns_upgrade(h, xt, xs, ns, 1, cbret)) < 0) + if ((ret = mod_ns_upgrade(h, xt, xmod, ns, cbret)) < 0) goto done; if (ret == 0) goto fail;