* Added flags to example backend to control its behaviour:
* Start with `-- -r` to run the reset plugin * Start with `-- -s` to run the state callback * Rewrote yang dir load algorithm to follow the algorithm in [FAQ](FAQ(doc/FAQ.md#how-are-yang-files-found) with more precise timestamp checks, etc.
This commit is contained in:
parent
8f656da15b
commit
606245ef02
20 changed files with 495 additions and 190 deletions
|
|
@ -44,6 +44,10 @@
|
||||||
```
|
```
|
||||||
|
|
||||||
### Minor changes
|
### Minor changes
|
||||||
|
* Added flags to example backend to control its behaviour:
|
||||||
|
* Start with `-- -r` to run the reset plugin
|
||||||
|
* Start with `-- -s` to run the state callback
|
||||||
|
* Rewrote yang dir load algorithm to follow the algorithm in [FAQ](FAQ(doc/FAQ.md#how-are-yang-files-found) with more precise timestamp checks, etc.
|
||||||
* Ensured you can add multiple callbacks for any RPC, including basic ones.
|
* Ensured you can add multiple callbacks for any RPC, including basic ones.
|
||||||
* Extra RPC:s will be called _after_ the basic ones.
|
* Extra RPC:s will be called _after_ the basic ones.
|
||||||
* One specific usecase is hook for `copy-config` (see [doc/ROADMAP.md](doc/ROADMAP.md) that can be implemented this way.
|
* One specific usecase is hook for `copy-config` (see [doc/ROADMAP.md](doc/ROADMAP.md) that can be implemented this way.
|
||||||
|
|
|
||||||
|
|
@ -568,11 +568,6 @@ from_client_validate(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
goto ok;
|
goto ok;
|
||||||
}
|
}
|
||||||
if (strcmp(db, "candidate") != 0 && strcmp(db, "tmp") != 0){
|
|
||||||
if (netconf_invalid_value(cbret, "protocol", "No such database")< 0)
|
|
||||||
goto done;
|
|
||||||
goto ok;
|
|
||||||
}
|
|
||||||
clicon_debug(1, "Validate %s", db);
|
clicon_debug(1, "Validate %s", db);
|
||||||
|
|
||||||
/* 1. Start transaction */
|
/* 1. Start transaction */
|
||||||
|
|
|
||||||
|
|
@ -596,7 +596,7 @@ main(int argc,
|
||||||
if (yang_spec_parse_module(h, str, clicon_yang_module_revision(h),
|
if (yang_spec_parse_module(h, str, clicon_yang_module_revision(h),
|
||||||
yspec) < 0)
|
yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
/* 3. Load all modules in a directory */
|
/* 3. Load all modules in a directory (will not overwrite file loaded ^) */
|
||||||
if ((str = clicon_yang_main_dir(h)) != NULL)
|
if ((str = clicon_yang_main_dir(h)) != NULL)
|
||||||
if (yang_spec_load_dir(h, str, yspec) < 0)
|
if (yang_spec_load_dir(h, str, yspec) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
|
||||||
|
|
@ -271,6 +271,11 @@ specific. The precedence of the options are as follows:
|
||||||
- `CLICON_YANG_MODULE_MAIN`
|
- `CLICON_YANG_MODULE_MAIN`
|
||||||
- `CLICON_YANG_MAIN_DIR`
|
- `CLICON_YANG_MAIN_DIR`
|
||||||
|
|
||||||
|
Note that using `CLICON_YANG_MAIN_DIR` Clixon may find several files
|
||||||
|
containing the same Yang module. Clixon will prefer the one without a
|
||||||
|
revision date if such a file exists. If no file has a revision date,
|
||||||
|
Clixon will prefer the newest.
|
||||||
|
|
||||||
## How do I enable Yang features?
|
## How do I enable Yang features?
|
||||||
|
|
||||||
Yang models have features, and parts of a specification can be
|
Yang models have features, and parts of a specification can be
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,8 @@ a real example would poll or get the interface counters via a system
|
||||||
call, as well as use the "xpath" argument to identify the requested
|
call, as well as use the "xpath" argument to identify the requested
|
||||||
state data.
|
state data.
|
||||||
|
|
||||||
|
The state data is enabled by starting the backend with: `-- -s`.
|
||||||
|
|
||||||
## Authentication and NACM
|
## Authentication and NACM
|
||||||
The example contains some stubs for authorization according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341):
|
The example contains some stubs for authorization according to [RFC8341(NACM)](https://tools.ietf.org/html/rfc8341):
|
||||||
* A basic auth HTTP callback, see: example_restconf_credentials() containing three example users: andy, wilma, and guest, according to the examples in Appendix A in [RFC8341](https://tools.ietf.org/html/rfc8341).
|
* A basic auth HTTP callback, see: example_restconf_credentials() containing three example users: andy, wilma, and guest, according to the examples in Appendix A in [RFC8341](https://tools.ietf.org/html/rfc8341).
|
||||||
|
|
|
||||||
|
|
@ -51,13 +51,19 @@
|
||||||
/* These include signatures for plugin and transaction callbacks. */
|
/* These include signatures for plugin and transaction callbacks. */
|
||||||
#include <clixon/clixon_backend.h>
|
#include <clixon/clixon_backend.h>
|
||||||
|
|
||||||
/* Variable to control if reset code is run.
|
/*! Variable to control if reset code is run.
|
||||||
* The reset code inserts "extra XML" which assumes ietf-interfaces is
|
* The reset code inserts "extra XML" which assumes ietf-interfaces is
|
||||||
* loaded, and this is not always the case.
|
* loaded, and this is not always the case.
|
||||||
* Therefore, the backend must be started with -- -r to enable the reset function
|
* Therefore, the backend must be started with -- -r to enable the reset function
|
||||||
*/
|
*/
|
||||||
static int _reset = 0;
|
static int _reset = 0;
|
||||||
|
|
||||||
|
/*! Variable to control if state code is run
|
||||||
|
* The state code adds extra non-config data
|
||||||
|
* Therefore, the backend must be started with -- -s to enable the state function
|
||||||
|
*/
|
||||||
|
static int _state = 0;
|
||||||
|
|
||||||
/* forward */
|
/* forward */
|
||||||
static int example_stream_timer_setup(clicon_handle h);
|
static int example_stream_timer_setup(clicon_handle h);
|
||||||
|
|
||||||
|
|
@ -210,7 +216,7 @@ example_copy_extra(clicon_handle h, /* Clicon handle */
|
||||||
type string;
|
type string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*
|
* This yang snippet is present in clixon-example.yang for exampl.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
example_statedata(clicon_handle h,
|
example_statedata(clicon_handle h,
|
||||||
|
|
@ -220,6 +226,8 @@ example_statedata(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
cxobj **xvec = NULL;
|
cxobj **xvec = NULL;
|
||||||
|
|
||||||
|
if (!_state)
|
||||||
|
goto ok;
|
||||||
/* Example of (static) statedata, real code would poll state
|
/* Example of (static) statedata, real code would poll state
|
||||||
* Note this state needs to be accomanied by yang snippet
|
* Note this state needs to be accomanied by yang snippet
|
||||||
* above
|
* above
|
||||||
|
|
@ -230,6 +238,7 @@ example_statedata(clicon_handle h,
|
||||||
"<op>43</op>" /* should not be ordered */
|
"<op>43</op>" /* should not be ordered */
|
||||||
"</state>", NULL, &xstate) < 0)
|
"</state>", NULL, &xstate) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
ok:
|
||||||
retval = 0;
|
retval = 0;
|
||||||
done:
|
done:
|
||||||
if (xvec)
|
if (xvec)
|
||||||
|
|
@ -277,6 +286,7 @@ example_reset(clicon_handle h,
|
||||||
int ret;
|
int ret;
|
||||||
cbuf *cbret = NULL;
|
cbuf *cbret = NULL;
|
||||||
|
|
||||||
|
if (!_reset)
|
||||||
goto ok; /* Note not enabled by default */
|
goto ok; /* Note not enabled by default */
|
||||||
if (xml_parse_string("<config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface>"
|
if (xml_parse_string("<config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface>"
|
||||||
"<name>lo</name><type>ex:loopback</type>"
|
"<name>lo</name><type>ex:loopback</type>"
|
||||||
|
|
@ -329,11 +339,14 @@ example_start(clicon_handle h,
|
||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
optind = 1;
|
optind = 1;
|
||||||
while ((c = getopt(argc, argv, "r")) != -1)
|
while ((c = getopt(argc, argv, "rs")) != -1)
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'r':
|
case 'r':
|
||||||
_reset = 1;
|
_reset = 1;
|
||||||
break;
|
break;
|
||||||
|
case 's':
|
||||||
|
_state = 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,6 @@ netconf_missing_element(cbuf *cb,
|
||||||
return retval;
|
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
|
||||||
* @param[out] xret Error XML tree. Free with xml_free after use
|
* @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"
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,9 @@
|
||||||
/*
|
/*
|
||||||
* Local variables
|
* Local variables
|
||||||
*/
|
*/
|
||||||
/* Mapping between yang keyword string <--> clicon constants */
|
/* Mapping between yang keyword string <--> clicon constants
|
||||||
|
* Here is also the place where doc on some types store variables (cv)
|
||||||
|
*/
|
||||||
static const map_str2int ykmap[] = {
|
static const map_str2int ykmap[] = {
|
||||||
{"anydata", Y_ANYDATA},
|
{"anydata", Y_ANYDATA},
|
||||||
{"anyxml", Y_ANYXML},
|
{"anyxml", Y_ANYXML},
|
||||||
|
|
@ -107,7 +109,7 @@ static const map_str2int ykmap[] = {
|
||||||
{"bit", Y_BIT},
|
{"bit", Y_BIT},
|
||||||
{"case", Y_CASE},
|
{"case", Y_CASE},
|
||||||
{"choice", Y_CHOICE},
|
{"choice", Y_CHOICE},
|
||||||
{"config", Y_CONFIG},
|
{"config", Y_CONFIG}, /* cv: boolean config flag */
|
||||||
{"contact", Y_CONTACT},
|
{"contact", Y_CONTACT},
|
||||||
{"container", Y_CONTAINER},
|
{"container", Y_CONTAINER},
|
||||||
{"default", Y_DEFAULT},
|
{"default", Y_DEFAULT},
|
||||||
|
|
@ -118,8 +120,8 @@ static const map_str2int ykmap[] = {
|
||||||
{"error-app-tag", Y_ERROR_APP_TAG},
|
{"error-app-tag", Y_ERROR_APP_TAG},
|
||||||
{"error_message", Y_ERROR_MESSAGE},
|
{"error_message", Y_ERROR_MESSAGE},
|
||||||
{"extension", Y_EXTENSION},
|
{"extension", Y_EXTENSION},
|
||||||
{"feature", Y_FEATURE},
|
{"feature", Y_FEATURE}, /* cv: feature as boolean */
|
||||||
{"fraction-digits", Y_FRACTION_DIGITS},
|
{"fraction-digits", Y_FRACTION_DIGITS}, /* cv: fraction-digits as uint8 */
|
||||||
{"grouping", Y_GROUPING},
|
{"grouping", Y_GROUPING},
|
||||||
{"identity", Y_IDENTITY},
|
{"identity", Y_IDENTITY},
|
||||||
{"if-feature", Y_IF_FEATURE},
|
{"if-feature", Y_IF_FEATURE},
|
||||||
|
|
@ -127,11 +129,11 @@ static const map_str2int ykmap[] = {
|
||||||
{"include", Y_INCLUDE},
|
{"include", Y_INCLUDE},
|
||||||
{"input", Y_INPUT},
|
{"input", Y_INPUT},
|
||||||
{"key", Y_KEY},
|
{"key", Y_KEY},
|
||||||
{"leaf", Y_LEAF},
|
{"leaf", Y_LEAF}, /* cv: store default value (if any)*/
|
||||||
{"leaf-list", Y_LEAF_LIST},
|
{"leaf-list", Y_LEAF_LIST}, /* cv: store default value (if any)*/
|
||||||
{"length", Y_LENGTH},
|
{"length", Y_LENGTH},
|
||||||
{"list", Y_LIST},
|
{"list", Y_LIST},
|
||||||
{"mandatory", Y_MANDATORY},
|
{"mandatory", Y_MANDATORY}, /* cv: store mandatory boolean */
|
||||||
{"max-elements", Y_MAX_ELEMENTS},
|
{"max-elements", Y_MAX_ELEMENTS},
|
||||||
{"min-elements", Y_MIN_ELEMENTS},
|
{"min-elements", Y_MIN_ELEMENTS},
|
||||||
{"modifier", Y_MODIFIER},
|
{"modifier", Y_MODIFIER},
|
||||||
|
|
@ -151,8 +153,8 @@ static const map_str2int ykmap[] = {
|
||||||
{"reference", Y_REFERENCE},
|
{"reference", Y_REFERENCE},
|
||||||
{"refine", Y_REFINE},
|
{"refine", Y_REFINE},
|
||||||
{"require-instance", Y_REQUIRE_INSTANCE},
|
{"require-instance", Y_REQUIRE_INSTANCE},
|
||||||
{"revision", Y_REVISION},
|
{"revision", Y_REVISION}, /* cv: YYYY-MM-DD as uint32 */
|
||||||
{"revision-date", Y_REVISION_DATE},
|
{"revision-date", Y_REVISION_DATE}, /* cv: YYYY-MM-DD as uint32 */
|
||||||
{"rpc", Y_RPC},
|
{"rpc", Y_RPC},
|
||||||
{"status", Y_STATUS},
|
{"status", Y_STATUS},
|
||||||
{"submodule", Y_SUBMODULE},
|
{"submodule", Y_SUBMODULE},
|
||||||
|
|
@ -160,7 +162,7 @@ static const map_str2int ykmap[] = {
|
||||||
{"typedef", Y_TYPEDEF},
|
{"typedef", Y_TYPEDEF},
|
||||||
{"unique", Y_UNIQUE},
|
{"unique", Y_UNIQUE},
|
||||||
{"units", Y_UNITS},
|
{"units", Y_UNITS},
|
||||||
{"unknown", Y_UNKNOWN},
|
{"unknown", Y_UNKNOWN}, /* cv: store extra string */
|
||||||
{"uses", Y_USES},
|
{"uses", Y_USES},
|
||||||
{"value", Y_VALUE},
|
{"value", Y_VALUE},
|
||||||
{"when", Y_WHEN},
|
{"when", Y_WHEN},
|
||||||
|
|
@ -171,6 +173,9 @@ static const map_str2int ykmap[] = {
|
||||||
{NULL, -1}
|
{NULL, -1}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* forward declaration */
|
||||||
|
static int ys_parse_date_arg(char *str, uint32_t *date);
|
||||||
|
|
||||||
/*! Create new yang specification
|
/*! Create new yang specification
|
||||||
* @retval yspec Free with yspec_free()
|
* @retval yspec Free with yspec_free()
|
||||||
* @retval NULL Error
|
* @retval NULL Error
|
||||||
|
|
@ -2514,6 +2519,13 @@ yang_spec_parse_file(clicon_handle h,
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see yang_spec_parse_file
|
* @see yang_spec_parse_file
|
||||||
|
* Load all yang files in a directory as primary objects.
|
||||||
|
* Some details if several same yang module x exists:
|
||||||
|
* 1) If x is already loaded (eg via direct file loading) skip it
|
||||||
|
* 2) Prefer x.yang over x@rev.yang (no revision)
|
||||||
|
* 3) If only x@rev.yang's found, prefer newest (newest revision)
|
||||||
|
* There is also an extra failsafe which may not be necessary, which removes
|
||||||
|
* the oldest module if 1-3 for some reason fails.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
yang_spec_load_dir(clicon_handle h,
|
yang_spec_load_dir(clicon_handle h,
|
||||||
|
|
@ -2524,13 +2536,26 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
int ndp;
|
int ndp;
|
||||||
struct dirent *dp = NULL;
|
struct dirent *dp = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
int j;
|
||||||
char filename[MAXPATHLEN];
|
char filename[MAXPATHLEN];
|
||||||
char *base = NULL; /* filename without dir */
|
char *base = NULL; /* filename without dir */
|
||||||
char *b;
|
|
||||||
int j;
|
|
||||||
int modnr;
|
int modnr;
|
||||||
|
yang_stmt *ym; /* yang module */
|
||||||
|
yang_stmt *ym0; /* (existing) yang module */
|
||||||
|
yang_stmt *yrev; /* yang revision */
|
||||||
|
uint32_t revf; /* revision in filename */
|
||||||
|
uint32_t revm; /* revision in parsed new module (same as revf) */
|
||||||
|
uint32_t rev0; /* revision in existing module */
|
||||||
|
char *s;
|
||||||
|
char *oldbase = NULL;
|
||||||
|
int taken = 0;
|
||||||
|
|
||||||
/* Get plugin objects names from plugin directory */
|
/* Get yang files names from yang module directory. Note that these
|
||||||
|
* are sorted alphatetically:
|
||||||
|
* a.yang,
|
||||||
|
* a@2000-01-01.yang,
|
||||||
|
* a@2111-11-11.yang
|
||||||
|
*/
|
||||||
if((ndp = clicon_file_dirent(dir, &dp, "(.yang)$", S_IFREG)) < 0)
|
if((ndp = clicon_file_dirent(dir, &dp, "(.yang)$", S_IFREG)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if (ndp == 0)
|
if (ndp == 0)
|
||||||
|
|
@ -2541,41 +2566,77 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
/* Load all yang files in dir */
|
/* Load all yang files in dir */
|
||||||
for (i = 0; i < ndp; i++) {
|
for (i = 0; i < ndp; i++) {
|
||||||
/* base = module name [+ @rev ] + .yang */
|
/* base = module name [+ @rev ] + .yang */
|
||||||
if (base)
|
if (oldbase)
|
||||||
free(base);
|
free(oldbase);
|
||||||
|
oldbase = base; base = NULL;
|
||||||
if ((base = strdup(dp[i].d_name)) == NULL){
|
if ((base = strdup(dp[i].d_name)) == NULL){
|
||||||
clicon_err(OE_UNIX, errno, "strdup");
|
clicon_err(OE_UNIX, errno, "strdup");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
clicon_debug(1, "%s %s", __FUNCTION__, base);
|
||||||
*rindex(base, '.') = '\0'; /* strip postfix .yang */
|
*rindex(base, '.') = '\0'; /* strip postfix .yang */
|
||||||
/* base = module name [+ @rev]
|
/* base = module name [+ @rev]
|
||||||
* if it hasnt @rev then prefer it (dont check other files w @rev)
|
* if it hasnt @rev then prefer it (dont check other files w @rev)
|
||||||
* Otherwise see if there is a newer
|
|
||||||
*/
|
*/
|
||||||
if ((b = index(base, '@')) != NULL){
|
revf = 0;
|
||||||
*b = '\0';
|
if ((s = index(base, '@')) != NULL){
|
||||||
/* base = module name */
|
*s++ = '\0';
|
||||||
|
if (ys_parse_date_arg(s, &revf) < 0)
|
||||||
/* Entries are sorted, see if later entry exists (include @), if so
|
|
||||||
* skip this one and take last.
|
|
||||||
* Assume file without @ is last
|
|
||||||
*/
|
|
||||||
for (j = (i+1); j < ndp; j++)
|
|
||||||
if (strncmp(base, dp[j].d_name, strlen(base)) == 0)
|
|
||||||
break;
|
|
||||||
if (j<ndp){ /* exists later entry */
|
|
||||||
clicon_debug(1, "%s skip %s", __FUNCTION__, dp[i].d_name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
|
||||||
/* Dont parse if already exists */
|
|
||||||
if (yang_find((yang_node*)yspec, Y_MODULE, base) != NULL ||
|
|
||||||
yang_find((yang_node*)yspec, Y_SUBMODULE, base) != NULL)
|
|
||||||
continue;
|
|
||||||
if (yang_parse_filename(filename, yspec) == NULL)
|
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
if (oldbase && strcmp(base, oldbase)) /* new yang file basename */
|
||||||
|
taken = 0;
|
||||||
|
if (revf == 0){ /* No revision: a.yang - take that */
|
||||||
|
taken = 1;
|
||||||
|
}
|
||||||
|
else{ /* a@xxx.yang */
|
||||||
|
if (taken)
|
||||||
|
continue; /* skip if already taken */
|
||||||
|
/* is there anyone else later? */
|
||||||
|
if (i+1<ndp && strncmp(base, dp[i+1].d_name, strlen(base)) == 0)
|
||||||
|
continue; /* same base: skip; */
|
||||||
|
taken = 1; /* last in line and not taken */
|
||||||
|
}
|
||||||
|
/* Here only a single file is reached(taken)
|
||||||
|
* Check if module already exists -> ym0/rev0 */
|
||||||
|
rev0 = 0;
|
||||||
|
if ((ym0 = yang_find((yang_node*)yspec, Y_MODULE, base)) != NULL ||
|
||||||
|
(ym0 = yang_find((yang_node*)yspec, Y_SUBMODULE, base)) != NULL){
|
||||||
|
yrev = yang_find((yang_node*)ym0, Y_REVISION, NULL);
|
||||||
|
rev0 = cv_uint32_get(yrev->ys_cv);
|
||||||
|
continue; /* skip if already added by specific file or module */
|
||||||
|
}
|
||||||
|
/* Create full filename */
|
||||||
|
snprintf(filename, MAXPATHLEN-1, "%s/%s", dir, dp[i].d_name);
|
||||||
|
if ((ym = yang_parse_filename(filename, yspec)) == NULL)
|
||||||
|
goto done;
|
||||||
|
revm = 0;
|
||||||
|
if ((yrev = yang_find((yang_node*)ym, Y_REVISION, NULL)) != NULL)
|
||||||
|
revm = cv_uint32_get(yrev->ys_cv);
|
||||||
|
/* Sanity check that file revision does not match internal rev stmt */
|
||||||
|
if (revf && revm && revm != revf){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "Yang module file revision and in yang does not match: %s vs %u", filename, revm);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
/* If ym0 and ym exists, delete the yang with oldest revision
|
||||||
|
* This is a failsafe in case anything else fails
|
||||||
|
*/
|
||||||
|
if (revm && rev0){
|
||||||
|
int size;
|
||||||
|
if (revm > rev0) /* Loaded module is older or eq -> remove ym */
|
||||||
|
ym = ym0;
|
||||||
|
for (j=0; j<yspec->yp_len; j++)
|
||||||
|
if (yspec->yp_stmt[j] == ym)
|
||||||
|
break;
|
||||||
|
size = (yspec->yp_len - j - 1)*sizeof(struct yang_stmt *);
|
||||||
|
memmove(&yspec->yp_stmt[j],
|
||||||
|
&yspec->yp_stmt[j+1],
|
||||||
|
size);
|
||||||
|
ys_free(ym);
|
||||||
|
yspec->yp_len--;
|
||||||
|
yspec->yp_stmt[yspec->yp_len] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (yang_parse_post(h, yspec, modnr) < 0)
|
if (yang_parse_post(h, yspec, modnr) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -2584,10 +2645,11 @@ yang_spec_load_dir(clicon_handle h,
|
||||||
free(dp);
|
free(dp);
|
||||||
if (base)
|
if (base)
|
||||||
free(base);
|
free(base);
|
||||||
|
if (oldbase)
|
||||||
|
free(oldbase);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Apply a function call recursively on all yang-stmt s recursively
|
/*! Apply a function call recursively on all yang-stmt s recursively
|
||||||
*
|
*
|
||||||
* Recursively traverse all yang-nodes in a parse-tree and apply fn(arg) for
|
* Recursively traverse all yang-nodes in a parse-tree and apply fn(arg) for
|
||||||
|
|
@ -2843,6 +2905,42 @@ yang_desc_schema_nodeid(yang_node *yn,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! parse yang date-arg string
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ys_parse_date_arg(char *str,
|
||||||
|
uint32_t *date)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int i;
|
||||||
|
uint32_t d = 0;
|
||||||
|
|
||||||
|
if (strlen(str) != 10 || str[4] != '-' || str[7] != '-'){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "Revision date %s, but expected: YYYY-MM-DD", str);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if ((i = cligen_tonum(4, str)) < 0){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "Revision date %s, but expected: YYYY-MM-DD", str);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
d = i*10000; /* year */
|
||||||
|
if ((i = cligen_tonum(2, &str[5])) < 0){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "Revision date %s, but expected: YYYY-MM-DD", str);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
d += i*100; /* month */
|
||||||
|
if ((i = cligen_tonum(2, &str[8])) < 0){
|
||||||
|
clicon_err(OE_YANG, EINVAL, "Revision date %s, but expected: YYYY-MM-DD", str);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
d += i; /* day */
|
||||||
|
*date = d;
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Parse argument as CV and save result in yang cv variable
|
/*! Parse argument as CV and save result in yang cv variable
|
||||||
*
|
*
|
||||||
* Note that some CV:s are parsed directly (eg fraction-digits) while others are parsed
|
* Note that some CV:s are parsed directly (eg fraction-digits) while others are parsed
|
||||||
|
|
@ -2897,6 +2995,7 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
uint8_t fd;
|
uint8_t fd;
|
||||||
|
uint32_t date = 0;
|
||||||
|
|
||||||
switch (ys->ys_keyword){
|
switch (ys->ys_keyword){
|
||||||
case Y_FRACTION_DIGITS:
|
case Y_FRACTION_DIGITS:
|
||||||
|
|
@ -2908,6 +3007,16 @@ ys_parse_sub(yang_stmt *ys,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Y_REVISION:
|
||||||
|
case Y_REVISION_DATE: /* YYYY-MM-DD encoded as uint32 YYYYMMDD */
|
||||||
|
if (ys_parse_date_arg(ys->ys_argument, &date) < 0)
|
||||||
|
goto done;
|
||||||
|
if ((ys->ys_cv = cv_new(CGV_UINT32)) == NULL){
|
||||||
|
clicon_err(OE_YANG, errno, "cv_new");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
cv_uint32_set(ys->ys_cv, date);
|
||||||
|
break;
|
||||||
case Y_UNKNOWN: /* XXX This code assumes ymod already loaded
|
case Y_UNKNOWN: /* XXX This code assumes ymod already loaded
|
||||||
but it may not be */
|
but it may not be */
|
||||||
if (extra == NULL)
|
if (extra == NULL)
|
||||||
|
|
@ -2998,7 +3107,6 @@ yang_config(yang_stmt *ys)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Given a yang node, translate the argument string to a cv vector
|
/*! Given a yang node, translate the argument string to a cv vector
|
||||||
*
|
*
|
||||||
* @param[in] ys Yang statement
|
* @param[in] ys Yang statement
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ fi
|
||||||
|
|
||||||
err=0
|
err=0
|
||||||
testnr=0
|
testnr=0
|
||||||
for test in test*.sh; do
|
for test in test_*.sh; do
|
||||||
if [ $testnr != 0 ]; then echo; fi
|
if [ $testnr != 0 ]; then echo; fi
|
||||||
testfile=$test
|
testfile=$test
|
||||||
. ./$test
|
. ./$test
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
|
|
||||||
# Site file, an example of this file in README.md
|
# Site file, an example of this file in README.md
|
||||||
if [ -f ./site.sh ]; then
|
if [ -f ./site.sh ]; then
|
||||||
|
|
||||||
. ./site.sh
|
. ./site.sh
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
return -1 # skip
|
return -1 # skip
|
||||||
|
|
@ -102,7 +101,8 @@ dir=/var/tmp/$0
|
||||||
if [ ! -d $dir ]; then
|
if [ ! -d $dir ]; then
|
||||||
mkdir $dir
|
mkdir $dir
|
||||||
fi
|
fi
|
||||||
# If we bring our own backend BE=0 (it is already started),the backend may
|
|
||||||
|
# If you bring your own backend BE=0 (it is already started),the backend may
|
||||||
# have created some files (eg unix socket) in $dir and therefore cannot
|
# have created some files (eg unix socket) in $dir and therefore cannot
|
||||||
# be deleted
|
# be deleted
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
|
|
@ -440,3 +440,4 @@ expectmatch(){
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
# include err() and new() functions and creates $dir
|
# include err() and new() functions and creates $dir
|
||||||
. ./lib.sh
|
|
||||||
|
|
||||||
cfg=$dir/conf_yang.xml
|
cfg=$dir/conf_yang.xml
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,9 +137,9 @@ if [ $BE -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
sleep 1
|
sleep 1
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg -- -s"
|
||||||
# start new backend
|
# start new backend
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg -- -s
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "kill old restconf daemon"
|
new "kill old restconf daemon"
|
||||||
|
|
|
||||||
|
|
@ -133,8 +133,8 @@ if [ $BE -ne 0 ]; then
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg -- -s"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg -- -s
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "kill old restconf daemon"
|
new "kill old restconf daemon"
|
||||||
|
|
|
||||||
|
|
@ -42,8 +42,8 @@ if [ $BE -ne 0 ]; then
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg -- -s"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg -- -s
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,7 @@ cat <<EOF > $dbdir/running_db
|
||||||
</config>
|
</config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
new "test params: -s running -f $cfg -y $fyang"
|
new "test params: -s running -f $cfg -y $fyang -- -s"
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
new "kill old backend"
|
new "kill old backend"
|
||||||
|
|
@ -156,7 +156,7 @@ if [ $BE -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend"
|
new "start backend"
|
||||||
start_backend -s running -f $cfg -y $fyang
|
start_backend -s running -f $cfg -y $fyang -- -s
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,8 @@ if [ $BE -ne 0 ]; then
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
err
|
err
|
||||||
fi
|
fi
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg -- -s"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg -- -s
|
||||||
fi
|
fi
|
||||||
|
|
||||||
new "kill old restconf daemon"
|
new "kill old restconf daemon"
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,14 @@
|
||||||
# This relieas on storing RFC7895 YANG Module Library modules-state info
|
# This relieas on storing RFC7895 YANG Module Library modules-state info
|
||||||
# in the datastore (or XML files?)
|
# in the datastore (or XML files?)
|
||||||
# The test is made with three Yang models A, B and C as follows:
|
# The test is made with three Yang models A, B and C as follows:
|
||||||
# Yang module A has revisions "814-01-28" and "2019-01-01"
|
# Yang module A has revisions "0814-01-28" and "2019-01-01"
|
||||||
# Yang module B has only revision "2019-01-01"
|
# Yang module B has only revision "2019-01-01"
|
||||||
# Yang module C has only revision "2019-01-01"
|
# Yang module C has only revision "2019-01-01"
|
||||||
# The system is started YANG modules:
|
# The system is started YANG modules:
|
||||||
# A revision "2019-01-01"
|
# A revision "2019-01-01"
|
||||||
# B revision "2019-01-01"
|
# B revision "2019-01-01"
|
||||||
# The (startup) configuration XML file has:
|
# The (startup) configuration XML file has:
|
||||||
# A revision "814-01-28";
|
# A revision "0814-01-28";
|
||||||
# B revision "2019-01-01"
|
# B revision "2019-01-01"
|
||||||
# C revision "2019-01-01"
|
# C revision "2019-01-01"
|
||||||
# Which means the following:
|
# Which means the following:
|
||||||
|
|
@ -19,24 +19,26 @@
|
||||||
# B has a compatible version
|
# B has a compatible version
|
||||||
# C is not present in the system
|
# C is not present in the system
|
||||||
|
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
||||||
# include err() and new() functions and creates $dir
|
|
||||||
. ./lib.sh
|
|
||||||
|
|
||||||
cfg=$dir/conf_yang.xml
|
cfg=$dir/conf_yang.xml
|
||||||
fyangA0=$dir/A@814-01-28.yang
|
fyangA0=$dir/A@0814-01-28.yang
|
||||||
fyangA1=$dir/A@2019-01-01.yang
|
fyangA1=$dir/A@2019-01-01.yang
|
||||||
fyangB=$dir/B@2019-01-01.yang
|
fyangB=$dir/B@2019-01-01.yang
|
||||||
|
|
||||||
# Yang module A revision "814-01-28"
|
# Yang module A revision "0814-01-28"
|
||||||
# Note that this Yang model will exist in the DIR but will not be loaded
|
# Note that this Yang model will exist in the DIR but will not be loaded
|
||||||
# by the system. Just here for reference
|
# by the system. Just here for reference
|
||||||
# XXX: Maybe it should be loaded and used in draft-wu?
|
# XXX: Maybe it should be loaded and used in draft-wu?
|
||||||
cat <<EOF > $fyangA0
|
cat <<EOF > $fyangA0
|
||||||
module A{
|
module A{
|
||||||
prefix a;
|
prefix a;
|
||||||
revision 814-01-28;
|
revision 0814-01-28;
|
||||||
namespace "urn:example:a";
|
namespace "urn:example:a";
|
||||||
leaf a0{
|
leaf a0{
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -52,7 +54,7 @@ cat <<EOF > $fyangA1
|
||||||
module A{
|
module A{
|
||||||
prefix a;
|
prefix a;
|
||||||
revision 2019-01-01;
|
revision 2019-01-01;
|
||||||
revision 814-01-28;
|
revision 0814-01-28;
|
||||||
namespace "urn:example:a";
|
namespace "urn:example:a";
|
||||||
/* leaf a0 has been removed */
|
/* leaf a0 has been removed */
|
||||||
leaf a1{
|
leaf a1{
|
||||||
|
|
@ -171,7 +173,7 @@ cat <<EOF > $dir/non-compat-valid.xml
|
||||||
<module-set-id>42</module-set-id>
|
<module-set-id>42</module-set-id>
|
||||||
<module>
|
<module>
|
||||||
<name>A</name>
|
<name>A</name>
|
||||||
<revision>814-01-28</revision>
|
<revision>0814-01-28</revision>
|
||||||
<namespace>urn:example:a</namespace>
|
<namespace>urn:example:a</namespace>
|
||||||
</module>
|
</module>
|
||||||
<module>
|
<module>
|
||||||
|
|
@ -198,7 +200,7 @@ cat <<EOF > $dir/non-compat-invalid.xml
|
||||||
<module-set-id>42</module-set-id>
|
<module-set-id>42</module-set-id>
|
||||||
<module>
|
<module>
|
||||||
<name>A</name>
|
<name>A</name>
|
||||||
<revision>814-01-28</revision>
|
<revision>0814-01-28</revision>
|
||||||
<namespace>urn:example:a</namespace>
|
<namespace>urn:example:a</namespace>
|
||||||
</module>
|
</module>
|
||||||
<module>
|
<module>
|
||||||
|
|
@ -332,7 +334,8 @@ runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1><b xmlns="
|
||||||
new "5. Load non-compat invalid startup. Enter failsafe, startup invalid."
|
new "5. Load non-compat invalid startup. Enter failsafe, startup invalid."
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
(cd $dir; cp non-compat-invalid.xml startup_db)
|
(cd $dir; cp non-compat-invalid.xml startup_db)
|
||||||
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>'
|
#runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>' # sorted
|
||||||
|
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><a0 xmlns="urn:example:a">old version</a0><c xmlns="urn:example:c">bla bla</c></data>' # unsorted
|
||||||
|
|
||||||
new "6. Load non-compat invalid running. Enter failsafe, startup invalid."
|
new "6. Load non-compat invalid running. Enter failsafe, startup invalid."
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
|
|
@ -345,7 +348,8 @@ runtest true running '<data><a1 xmlns="urn:example:a">always work</a1></data>' '
|
||||||
new "7. Load compatible invalid startup."
|
new "7. Load compatible invalid startup."
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
(cd $dir; cp compat-invalid.xml startup_db)
|
(cd $dir; cp compat-invalid.xml startup_db)
|
||||||
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>'
|
#runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a0 xmlns="urn:example:a">old version</a0><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><c xmlns="urn:example:c">bla bla</c></data>' # sorted
|
||||||
|
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<data><a1 xmlns="urn:example:a">always work</a1><b xmlns="urn:example:b">other text</b><a0 xmlns="urn:example:a">old version</a0><c xmlns="urn:example:c">bla bla</c></data>' # unsorted
|
||||||
|
|
||||||
# This testcase contains an error/exception of the clixon xml parser, and
|
# This testcase contains an error/exception of the clixon xml parser, and
|
||||||
# I cant track down the memory leakage.
|
# I cant track down the memory leakage.
|
||||||
|
|
@ -354,8 +358,7 @@ new "8. Load non-compat startup. Syntax fail, enter failsafe, startup invalid"
|
||||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
(cd $dir; cp compat-err.xml startup_db)
|
(cd $dir; cp compat-err.xml startup_db)
|
||||||
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>read registry</error-message></rpc-error>'
|
runtest true startup '<data><a1 xmlns="urn:example:a">always work</a1></data>' '<rpc-error><error-type>application</error-type><error-tag>operation-failed</error-tag><error-severity>error</error-severity><error-message>read registry</error-message></rpc-error>'
|
||||||
|
fi # valgrindtest
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $BE -ne 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
|
|
||||||
145
test/test_upgrade_repair.sh
Executable file
145
test/test_upgrade_repair.sh
Executable file
|
|
@ -0,0 +1,145 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# Start clixon with module A rec 2019
|
||||||
|
# Load startup with non-compatible and invalid module A with rev 0814-01-28
|
||||||
|
# Go into fail-safe with invalid startup
|
||||||
|
|
||||||
|
# Magic line must be first in script (see README.md)
|
||||||
|
s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
|
APPNAME=example
|
||||||
|
|
||||||
|
cfg=$dir/conf_yang.xml
|
||||||
|
fyangA0=$dir/A@0814-01-28.yang
|
||||||
|
fyangA1=$dir/A@2019-01-01.yang
|
||||||
|
|
||||||
|
# Yang module A revision "0814-01-28"
|
||||||
|
# Note that this Yang model will exist in the DIR but will not be loaded
|
||||||
|
# by the system. Just here for reference
|
||||||
|
# XXX: Maybe it should be loaded and used in draft-wu?
|
||||||
|
cat <<EOF > $fyangA0
|
||||||
|
module A{
|
||||||
|
prefix a;
|
||||||
|
revision 0814-01-28;
|
||||||
|
namespace "urn:example:a";
|
||||||
|
leaf a0{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf a1{
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Yang module A revision "2019-01-01"
|
||||||
|
cat <<EOF > $fyangA1
|
||||||
|
module A{
|
||||||
|
prefix a;
|
||||||
|
revision 2019-01-01;
|
||||||
|
revision 0814-01-28;
|
||||||
|
namespace "urn:example:a";
|
||||||
|
/* leaf a0 has been removed */
|
||||||
|
leaf a1{
|
||||||
|
description "exists in both versions";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
leaf a2{
|
||||||
|
description "has been added";
|
||||||
|
type string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create configuration
|
||||||
|
cat <<EOF > $cfg
|
||||||
|
<clixon-config xmlns="http://clicon.org/config">
|
||||||
|
<CLICON_CONFIGFILE>$cfg</CLICON_CONFIGFILE>
|
||||||
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
|
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
||||||
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
|
<CLICON_BACKEND_DIR>/usr/local/lib/example/backend</CLICON_BACKEND_DIR>
|
||||||
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
|
<CLICON_XMLDB_DIR>$dir</CLICON_XMLDB_DIR>
|
||||||
|
<CLICON_XMLDB_PLUGIN>/usr/local/lib/xmldb/text.so</CLICON_XMLDB_PLUGIN>
|
||||||
|
<CLICON_XMLDB_MODSTATE>true</CLICON_XMLDB_MODSTATE>
|
||||||
|
<CLICON_CLISPEC_DIR>/usr/local/lib/$APPNAME/clispec</CLICON_CLISPEC_DIR>
|
||||||
|
<CLICON_CLI_DIR>/usr/local/lib/$APPNAME/cli</CLICON_CLI_DIR>
|
||||||
|
<CLICON_CLI_MODE>$APPNAME</CLICON_CLI_MODE>
|
||||||
|
</clixon-config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create failsafe db
|
||||||
|
cat <<EOF > $dir/failsafe_db
|
||||||
|
<config>
|
||||||
|
<a1 xmlns="urn:example:a">always work</a1>
|
||||||
|
</config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create non-compat startup db
|
||||||
|
# startup config XML with following (A obsolete, B OK, C lacking)
|
||||||
|
cat <<EOF > $dir/non-compat-invalid.xml
|
||||||
|
<config>
|
||||||
|
<modules-state xmlns="urn:ietf:params:xml:ns:yang:ietf-yang-library">
|
||||||
|
<module-set-id>42</module-set-id>
|
||||||
|
<module>
|
||||||
|
<name>A</name>
|
||||||
|
<revision>0814-01-28</revision>
|
||||||
|
<namespace>urn:example:a</namespace>
|
||||||
|
</module>
|
||||||
|
</modules-state>
|
||||||
|
<a0 xmlns="urn:example:a">old version</a0>
|
||||||
|
<a1 xmlns="urn:example:a">always work</a1>
|
||||||
|
</config>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||||
|
(cd $dir; cp non-compat-invalid.xml startup_db)
|
||||||
|
|
||||||
|
mode=startup
|
||||||
|
|
||||||
|
new "test params: -f $cfg"
|
||||||
|
# Bring your own backend
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
|
# kill old backend (if any)
|
||||||
|
new "kill old backend"
|
||||||
|
sudo clixon_backend -zf $cfg
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
err
|
||||||
|
fi
|
||||||
|
new "start backend -s $mode -f $cfg"
|
||||||
|
start_backend -s $mode -f $cfg
|
||||||
|
fi
|
||||||
|
new "waiting"
|
||||||
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
new "kill old restconf daemon"
|
||||||
|
sudo pkill -u www-data clixon_restconf
|
||||||
|
|
||||||
|
new "start restconf daemon"
|
||||||
|
start_restconf -f $cfg
|
||||||
|
|
||||||
|
new "waiting"
|
||||||
|
sleep $RCWAIT
|
||||||
|
|
||||||
|
new "Check running db content is failsafe"
|
||||||
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><get-config><source><running/></source></get-config></rpc>]]>]]>' '^<rpc-reply><data><a1 xmlns="urn:example:a">always work</a1></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
#repair
|
||||||
|
|
||||||
|
#exit
|
||||||
|
|
||||||
|
new "Kill restconf daemon"
|
||||||
|
stop_restconf
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
|
new "Kill backend"
|
||||||
|
# Check if premature kill
|
||||||
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
if [ -z "$pid" ]; then
|
||||||
|
err "backend already dead"
|
||||||
|
fi
|
||||||
|
# kill backend
|
||||||
|
stop_backend -f $cfg
|
||||||
|
|
||||||
|
rm -rf $dir
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
@ -10,16 +10,20 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
||||||
|
|
||||||
APPNAME=example
|
APPNAME=example
|
||||||
|
|
||||||
|
OLDDATE=0814-01-28 # This is alphabeticaly after 2018-12-02
|
||||||
|
NEWDATE=2018-12-02
|
||||||
|
|
||||||
cfg=$dir/conf_yang.xml
|
cfg=$dir/conf_yang.xml
|
||||||
fyang1=$dir/$APPNAME@2018-12-02.yang
|
fyang1=$dir/$APPNAME@2018-12-02.yang
|
||||||
fyang2=$dir/$APPNAME@2018-01-01.yang
|
fyang2=$dir/$APPNAME@$OLDDATE.yang
|
||||||
fyang3=$dir/other.yang
|
fyang3=$dir/other.yang
|
||||||
|
|
||||||
# 1st variant of the example module
|
# 1st variant of the example module
|
||||||
cat <<EOF > $fyang1
|
cat <<EOF > $fyang1
|
||||||
module example{
|
module example{
|
||||||
prefix ex;
|
prefix ex;
|
||||||
revision 2018-12-02;
|
revision $NEWDATE;
|
||||||
|
revision $OLDDATE;
|
||||||
namespace "urn:example:clixon";
|
namespace "urn:example:clixon";
|
||||||
leaf newex{
|
leaf newex{
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -31,7 +35,7 @@ EOF
|
||||||
cat <<EOF > $fyang2
|
cat <<EOF > $fyang2
|
||||||
module example{
|
module example{
|
||||||
prefix ex;
|
prefix ex;
|
||||||
revision 2018-01-01;
|
revision $OLDDATE;
|
||||||
namespace "urn:example:clixon";
|
namespace "urn:example:clixon";
|
||||||
leaf oldex{
|
leaf oldex{
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -43,7 +47,7 @@ EOF
|
||||||
cat <<EOF > $fyang3
|
cat <<EOF > $fyang3
|
||||||
module other{
|
module other{
|
||||||
prefix oth;
|
prefix oth;
|
||||||
revision 2018-01-01;
|
revision $NEWDATE;
|
||||||
namespace "urn:example:clixon2";
|
namespace "urn:example:clixon2";
|
||||||
leaf other{
|
leaf other{
|
||||||
type string;
|
type string;
|
||||||
|
|
@ -94,10 +98,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other should fail"
|
new "Set other should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
if [ $BE -eq 0 ]; then
|
if [ $BE -ne 0 ]; then
|
||||||
exit # BE
|
|
||||||
fi
|
|
||||||
|
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -107,6 +108,7 @@ fi
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "2. Load old module as file"
|
new "2. Load old module as file"
|
||||||
|
|
@ -128,12 +130,14 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
# start new backend
|
# start new backend
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
|
|
||||||
new "Set oldex"
|
new "Set oldex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
@ -144,6 +148,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other should fail"
|
new "Set other should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -153,6 +158,7 @@ fi
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "3. Load module with no revision"
|
new "3. Load module with no revision"
|
||||||
|
|
@ -170,11 +176,13 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
|
|
||||||
new "Set newex"
|
new "Set newex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><newex xmlns="urn:example:clixon">str</newex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><newex xmlns="urn:example:clixon">str</newex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
@ -185,6 +193,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other should fail"
|
new "Set other should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -193,6 +202,7 @@ if [ -z "$pid" ]; then
|
||||||
fi
|
fi
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "4. Load module with old revision"
|
new "4. Load module with old revision"
|
||||||
|
|
@ -203,7 +213,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>/usr/local/share/clixon</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||||
<CLICON_YANG_MODULE_REVISION>2018-01-01</CLICON_YANG_MODULE_REVISION>
|
<CLICON_YANG_MODULE_REVISION>$OLDDATE</CLICON_YANG_MODULE_REVISION>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
|
@ -211,11 +221,13 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
|
|
||||||
new "Set oldex"
|
new "Set oldex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
@ -226,6 +238,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other should fail"
|
new "Set other should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -235,6 +248,7 @@ fi
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "5. Load dir"
|
new "5. Load dir"
|
||||||
|
|
@ -252,11 +266,13 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
|
|
||||||
new "Set newex"
|
new "Set newex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><newex xmlns="urn:example:clixon">str</newex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><newex xmlns="urn:example:clixon">str</newex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
@ -267,15 +283,18 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other"
|
new "Set other"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
if [ -z "$pid" ]; then
|
if [ -z "$pid" ]; then
|
||||||
err "backend already dead"
|
err "backend already dead"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "6. Load dir override with file"
|
new "6. Load dir override with file"
|
||||||
|
|
@ -294,12 +313,13 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
new "Set oldex"
|
new "Set oldex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
|
@ -309,6 +329,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other"
|
new "Set other"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -318,7 +339,7 @@ fi
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "7. Load dir override with module + revision"
|
new "7. Load dir override with module + revision"
|
||||||
|
|
@ -330,7 +351,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
||||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||||
<CLICON_YANG_MODULE_REVISION>2018-01-01</CLICON_YANG_MODULE_REVISION>
|
<CLICON_YANG_MODULE_REVISION>$OLDDATE</CLICON_YANG_MODULE_REVISION>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
|
@ -338,11 +359,13 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
|
|
||||||
new "Set oldex"
|
new "Set oldex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
@ -353,6 +376,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other"
|
new "Set other"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -362,6 +386,7 @@ fi
|
||||||
# kill backend
|
# kill backend
|
||||||
stop_backend -f $cfg
|
stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
fi
|
||||||
|
|
||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
new "8. Load module w new revision overrided by old file"
|
new "8. Load module w new revision overrided by old file"
|
||||||
|
|
@ -373,7 +398,7 @@ cat <<EOF > $cfg
|
||||||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||||
<CLICON_YANG_MAIN_FILE>$fyang2</CLICON_YANG_MAIN_FILE>
|
<CLICON_YANG_MAIN_FILE>$fyang2</CLICON_YANG_MAIN_FILE>
|
||||||
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
<CLICON_YANG_MODULE_MAIN>example</CLICON_YANG_MODULE_MAIN>
|
||||||
<CLICON_YANG_MODULE_REVISION>2018-12-02</CLICON_YANG_MODULE_REVISION>
|
<CLICON_YANG_MODULE_REVISION>$NEWDATE</CLICON_YANG_MODULE_REVISION>
|
||||||
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
<CLICON_SOCK>/usr/local/var/$APPNAME/$APPNAME.sock</CLICON_SOCK>
|
||||||
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
<CLICON_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||||
|
|
@ -381,11 +406,13 @@ cat <<EOF > $cfg
|
||||||
</clixon-config>
|
</clixon-config>
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "start backend -s init -f $cfg"
|
new "start backend -s init -f $cfg"
|
||||||
start_backend -s init -f $cfg
|
start_backend -s init -f $cfg
|
||||||
|
|
||||||
new "waiting"
|
new "waiting"
|
||||||
sleep $RCWAIT
|
sleep $RCWAIT
|
||||||
|
fi
|
||||||
|
|
||||||
new "Set oldex"
|
new "Set oldex"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><oldex xmlns="urn:example:clixon">str</oldex></config></edit-config></rpc>]]>]]>' '^<rpc-reply><ok/></rpc-reply>]]>]]>$'
|
||||||
|
|
@ -396,6 +423,7 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
||||||
new "Set other should fail"
|
new "Set other should fail"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></target><config><other xmlns="urn:example:clixon2">str</other></config></edit-config></rpc>]]>]]>' '^<rpc-reply><rpc-error><error-type>application</error-type><error-tag>unknown-element</error-tag><error-info><bad-element>other</bad-element></error-info><error-severity>error</error-severity><error-message>Unassigned yang spec</error-message></rpc-error></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
|
if [ $BE -ne 0 ]; then
|
||||||
new "Kill backend"
|
new "Kill backend"
|
||||||
# Check if premature kill
|
# Check if premature kill
|
||||||
pid=`pgrep -u root -f clixon_backend`
|
pid=`pgrep -u root -f clixon_backend`
|
||||||
|
|
@ -407,3 +435,6 @@ stop_backend -f $cfg
|
||||||
sudo pkill -u root -f clixon_backend
|
sudo pkill -u root -f clixon_backend
|
||||||
|
|
||||||
rm -rf $dir
|
rm -rf $dir
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ new "netconf get config example1 and example2"
|
||||||
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" '^<rpc-reply><data><x xmlns="urn:example:clixon1">42</x><x xmlns="urn:example:clixon2"><y>99</y></x></data></rpc-reply>]]>]]>$'
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><get-config><source><candidate/></source></get-config></rpc>]]>]]>" '^<rpc-reply><data><x xmlns="urn:example:clixon1">42</x><x xmlns="urn:example:clixon2"><y>99</y></x></data></rpc-reply>]]>]]>$'
|
||||||
|
|
||||||
new "netconf discard-changes"
|
new "netconf discard-changes"
|
||||||
expecteof "$clixon_netconf -qf $cfg -y $fyang1" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
expecteof "$clixon_netconf -qf $cfg" 0 "<rpc><discard-changes/></rpc>]]>]]>" "^<rpc-reply><ok/></rpc-reply>]]>]]>$"
|
||||||
|
|
||||||
new "restconf set x in example1"
|
new "restconf set x in example1"
|
||||||
expecteq "$(curl -s -X POST -d '{"example1:x":42}' http://localhost/restconf/data)" 0 ''
|
expecteq "$(curl -s -X POST -d '{"example1:x":42}' http://localhost/restconf/data)" 0 ''
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue