* 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
|
||||
* 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.
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -568,11 +568,6 @@ from_client_validate(clicon_handle h,
|
|||
goto done;
|
||||
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);
|
||||
|
||||
/* 1. Start transaction */
|
||||
|
|
|
|||
|
|
@ -596,7 +596,7 @@ main(int argc,
|
|||
if (yang_spec_parse_module(h, str, clicon_yang_module_revision(h),
|
||||
yspec) < 0)
|
||||
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 (yang_spec_load_dir(h, str, yspec) < 0)
|
||||
goto done;
|
||||
|
|
|
|||
|
|
@ -271,6 +271,11 @@ specific. The precedence of the options are as follows:
|
|||
- `CLICON_YANG_MODULE_MAIN`
|
||||
- `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?
|
||||
|
||||
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
|
||||
state data.
|
||||
|
||||
The state data is enabled by starting the backend with: `-- -s`.
|
||||
|
||||
## Authentication and NACM
|
||||
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).
|
||||
|
|
|
|||
|
|
@ -51,13 +51,19 @@
|
|||
/* These include signatures for plugin and transaction callbacks. */
|
||||
#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
|
||||
* loaded, and this is not always the case.
|
||||
* Therefore, the backend must be started with -- -r to enable the reset function
|
||||
*/
|
||||
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 */
|
||||
static int example_stream_timer_setup(clicon_handle h);
|
||||
|
||||
|
|
@ -210,7 +216,7 @@ example_copy_extra(clicon_handle h, /* Clicon handle */
|
|||
type string;
|
||||
}
|
||||
}
|
||||
*
|
||||
* This yang snippet is present in clixon-example.yang for exampl.
|
||||
*/
|
||||
int
|
||||
example_statedata(clicon_handle h,
|
||||
|
|
@ -220,6 +226,8 @@ example_statedata(clicon_handle h,
|
|||
int retval = -1;
|
||||
cxobj **xvec = NULL;
|
||||
|
||||
if (!_state)
|
||||
goto ok;
|
||||
/* Example of (static) statedata, real code would poll state
|
||||
* Note this state needs to be accomanied by yang snippet
|
||||
* above
|
||||
|
|
@ -230,6 +238,7 @@ example_statedata(clicon_handle h,
|
|||
"<op>43</op>" /* should not be ordered */
|
||||
"</state>", NULL, &xstate) < 0)
|
||||
goto done;
|
||||
ok:
|
||||
retval = 0;
|
||||
done:
|
||||
if (xvec)
|
||||
|
|
@ -277,6 +286,7 @@ example_reset(clicon_handle h,
|
|||
int ret;
|
||||
cbuf *cbret = NULL;
|
||||
|
||||
if (!_reset)
|
||||
goto ok; /* Note not enabled by default */
|
||||
if (xml_parse_string("<config><interfaces xmlns=\"urn:ietf:params:xml:ns:yang:ietf-interfaces\"><interface>"
|
||||
"<name>lo</name><type>ex:loopback</type>"
|
||||
|
|
@ -329,11 +339,14 @@ example_start(clicon_handle h,
|
|||
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
while ((c = getopt(argc, argv, "r")) != -1)
|
||||
while ((c = getopt(argc, argv, "rs")) != -1)
|
||||
switch (c) {
|
||||
case 'r':
|
||||
_reset = 1;
|
||||
break;
|
||||
case 's':
|
||||
_state = 1;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,7 +376,6 @@ netconf_missing_element(cbuf *cb,
|
|||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! Create Netconf missing-element error XML tree according to RFC 6241 App A
|
||||
* @param[out] xret Error XML tree. Free with xml_free after use
|
||||
* @param[in] type Error type: "application" or "protocol"
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@
|
|||
/*
|
||||
* 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[] = {
|
||||
{"anydata", Y_ANYDATA},
|
||||
{"anyxml", Y_ANYXML},
|
||||
|
|
@ -107,7 +109,7 @@ static const map_str2int ykmap[] = {
|
|||
{"bit", Y_BIT},
|
||||
{"case", Y_CASE},
|
||||
{"choice", Y_CHOICE},
|
||||
{"config", Y_CONFIG},
|
||||
{"config", Y_CONFIG}, /* cv: boolean config flag */
|
||||
{"contact", Y_CONTACT},
|
||||
{"container", Y_CONTAINER},
|
||||
{"default", Y_DEFAULT},
|
||||
|
|
@ -118,8 +120,8 @@ static const map_str2int ykmap[] = {
|
|||
{"error-app-tag", Y_ERROR_APP_TAG},
|
||||
{"error_message", Y_ERROR_MESSAGE},
|
||||
{"extension", Y_EXTENSION},
|
||||
{"feature", Y_FEATURE},
|
||||
{"fraction-digits", Y_FRACTION_DIGITS},
|
||||
{"feature", Y_FEATURE}, /* cv: feature as boolean */
|
||||
{"fraction-digits", Y_FRACTION_DIGITS}, /* cv: fraction-digits as uint8 */
|
||||
{"grouping", Y_GROUPING},
|
||||
{"identity", Y_IDENTITY},
|
||||
{"if-feature", Y_IF_FEATURE},
|
||||
|
|
@ -127,11 +129,11 @@ static const map_str2int ykmap[] = {
|
|||
{"include", Y_INCLUDE},
|
||||
{"input", Y_INPUT},
|
||||
{"key", Y_KEY},
|
||||
{"leaf", Y_LEAF},
|
||||
{"leaf-list", Y_LEAF_LIST},
|
||||
{"leaf", Y_LEAF}, /* cv: store default value (if any)*/
|
||||
{"leaf-list", Y_LEAF_LIST}, /* cv: store default value (if any)*/
|
||||
{"length", Y_LENGTH},
|
||||
{"list", Y_LIST},
|
||||
{"mandatory", Y_MANDATORY},
|
||||
{"mandatory", Y_MANDATORY}, /* cv: store mandatory boolean */
|
||||
{"max-elements", Y_MAX_ELEMENTS},
|
||||
{"min-elements", Y_MIN_ELEMENTS},
|
||||
{"modifier", Y_MODIFIER},
|
||||
|
|
@ -151,8 +153,8 @@ static const map_str2int ykmap[] = {
|
|||
{"reference", Y_REFERENCE},
|
||||
{"refine", Y_REFINE},
|
||||
{"require-instance", Y_REQUIRE_INSTANCE},
|
||||
{"revision", Y_REVISION},
|
||||
{"revision-date", Y_REVISION_DATE},
|
||||
{"revision", Y_REVISION}, /* cv: YYYY-MM-DD as uint32 */
|
||||
{"revision-date", Y_REVISION_DATE}, /* cv: YYYY-MM-DD as uint32 */
|
||||
{"rpc", Y_RPC},
|
||||
{"status", Y_STATUS},
|
||||
{"submodule", Y_SUBMODULE},
|
||||
|
|
@ -160,7 +162,7 @@ static const map_str2int ykmap[] = {
|
|||
{"typedef", Y_TYPEDEF},
|
||||
{"unique", Y_UNIQUE},
|
||||
{"units", Y_UNITS},
|
||||
{"unknown", Y_UNKNOWN},
|
||||
{"unknown", Y_UNKNOWN}, /* cv: store extra string */
|
||||
{"uses", Y_USES},
|
||||
{"value", Y_VALUE},
|
||||
{"when", Y_WHEN},
|
||||
|
|
@ -171,6 +173,9 @@ static const map_str2int ykmap[] = {
|
|||
{NULL, -1}
|
||||
};
|
||||
|
||||
/* forward declaration */
|
||||
static int ys_parse_date_arg(char *str, uint32_t *date);
|
||||
|
||||
/*! Create new yang specification
|
||||
* @retval yspec Free with yspec_free()
|
||||
* @retval NULL Error
|
||||
|
|
@ -2514,6 +2519,13 @@ yang_spec_parse_file(clicon_handle h,
|
|||
* @retval 0 OK
|
||||
* @retval -1 Error
|
||||
* @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
|
||||
yang_spec_load_dir(clicon_handle h,
|
||||
|
|
@ -2524,13 +2536,26 @@ yang_spec_load_dir(clicon_handle h,
|
|||
int ndp;
|
||||
struct dirent *dp = NULL;
|
||||
int i;
|
||||
int j;
|
||||
char filename[MAXPATHLEN];
|
||||
char *base = NULL; /* filename without dir */
|
||||
char *b;
|
||||
int j;
|
||||
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)
|
||||
goto done;
|
||||
if (ndp == 0)
|
||||
|
|
@ -2541,41 +2566,77 @@ yang_spec_load_dir(clicon_handle h,
|
|||
/* Load all yang files in dir */
|
||||
for (i = 0; i < ndp; i++) {
|
||||
/* base = module name [+ @rev ] + .yang */
|
||||
if (base)
|
||||
free(base);
|
||||
if (oldbase)
|
||||
free(oldbase);
|
||||
oldbase = base; base = NULL;
|
||||
if ((base = strdup(dp[i].d_name)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
clicon_debug(1, "%s %s", __FUNCTION__, base);
|
||||
*rindex(base, '.') = '\0'; /* strip postfix .yang */
|
||||
/* base = module name [+ @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){
|
||||
*b = '\0';
|
||||
/* base = module name */
|
||||
|
||||
/* 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)
|
||||
revf = 0;
|
||||
if ((s = index(base, '@')) != NULL){
|
||||
*s++ = '\0';
|
||||
if (ys_parse_date_arg(s, &revf) < 0)
|
||||
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)
|
||||
goto done;
|
||||
retval = 0;
|
||||
|
|
@ -2584,10 +2645,11 @@ yang_spec_load_dir(clicon_handle h,
|
|||
free(dp);
|
||||
if (base)
|
||||
free(base);
|
||||
if (oldbase)
|
||||
free(oldbase);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*! 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
|
||||
|
|
@ -2843,6 +2905,42 @@ yang_desc_schema_nodeid(yang_node *yn,
|
|||
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
|
||||
*
|
||||
* 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;
|
||||
uint8_t fd;
|
||||
uint32_t date = 0;
|
||||
|
||||
switch (ys->ys_keyword){
|
||||
case Y_FRACTION_DIGITS:
|
||||
|
|
@ -2908,6 +3007,16 @@ ys_parse_sub(yang_stmt *ys,
|
|||
goto done;
|
||||
}
|
||||
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
|
||||
but it may not be */
|
||||
if (extra == NULL)
|
||||
|
|
@ -2998,7 +3107,6 @@ yang_config(yang_stmt *ys)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*! Given a yang node, translate the argument string to a cv vector
|
||||
*
|
||||
* @param[in] ys Yang statement
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ fi
|
|||
|
||||
err=0
|
||||
testnr=0
|
||||
for test in test*.sh; do
|
||||
for test in test_*.sh; do
|
||||
if [ $testnr != 0 ]; then echo; fi
|
||||
testfile=$test
|
||||
. ./$test
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
# Site file, an example of this file in README.md
|
||||
if [ -f ./site.sh ]; then
|
||||
|
||||
. ./site.sh
|
||||
if [ $? -ne 0 ]; then
|
||||
return -1 # skip
|
||||
|
|
@ -102,7 +101,8 @@ dir=/var/tmp/$0
|
|||
if [ ! -d $dir ]; then
|
||||
mkdir $dir
|
||||
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
|
||||
# be deleted
|
||||
if [ $BE -ne 0 ]; then
|
||||
|
|
@ -440,3 +440,4 @@ expectmatch(){
|
|||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ s="$_" ; . ./lib.sh || if [ "$s" = $0 ]; then exit 0; else return 0; fi
|
|||
|
||||
APPNAME=example
|
||||
# include err() and new() functions and creates $dir
|
||||
. ./lib.sh
|
||||
|
||||
cfg=$dir/conf_yang.xml
|
||||
|
||||
|
|
|
|||
|
|
@ -137,9 +137,9 @@ if [ $BE -ne 0 ]; then
|
|||
err
|
||||
fi
|
||||
sleep 1
|
||||
new "start backend -s init -f $cfg"
|
||||
new "start backend -s init -f $cfg -- -s"
|
||||
# start new backend
|
||||
start_backend -s init -f $cfg
|
||||
start_backend -s init -f $cfg -- -s
|
||||
fi
|
||||
|
||||
new "kill old restconf daemon"
|
||||
|
|
|
|||
|
|
@ -133,8 +133,8 @@ if [ $BE -ne 0 ]; then
|
|||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
new "start backend -s init -f $cfg -- -s"
|
||||
start_backend -s init -f $cfg -- -s
|
||||
fi
|
||||
|
||||
new "kill old restconf daemon"
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ if [ $BE -ne 0 ]; then
|
|||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
new "start backend -s init -f $cfg -- -s"
|
||||
start_backend -s init -f $cfg -- -s
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ cat <<EOF > $dbdir/running_db
|
|||
</config>
|
||||
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
|
||||
new "kill old backend"
|
||||
|
|
@ -156,7 +156,7 @@ if [ $BE -ne 0 ]; then
|
|||
err
|
||||
fi
|
||||
new "start backend"
|
||||
start_backend -s running -f $cfg -y $fyang
|
||||
start_backend -s running -f $cfg -y $fyang -- -s
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ if [ $BE -ne 0 ]; then
|
|||
if [ $? -ne 0 ]; then
|
||||
err
|
||||
fi
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
new "start backend -s init -f $cfg -- -s"
|
||||
start_backend -s init -f $cfg -- -s
|
||||
fi
|
||||
|
||||
new "kill old restconf daemon"
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@
|
|||
# This relieas on storing RFC7895 YANG Module Library modules-state info
|
||||
# in the datastore (or XML files?)
|
||||
# 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 C has only revision "2019-01-01"
|
||||
# The system is started YANG modules:
|
||||
# A revision "2019-01-01"
|
||||
# B revision "2019-01-01"
|
||||
# The (startup) configuration XML file has:
|
||||
# A revision "814-01-28";
|
||||
# A revision "0814-01-28";
|
||||
# B revision "2019-01-01"
|
||||
# C revision "2019-01-01"
|
||||
# Which means the following:
|
||||
|
|
@ -19,24 +19,26 @@
|
|||
# B has a compatible version
|
||||
# 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
|
||||
|
||||
# include err() and new() functions and creates $dir
|
||||
. ./lib.sh
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
# 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 814-01-28;
|
||||
revision 0814-01-28;
|
||||
namespace "urn:example:a";
|
||||
leaf a0{
|
||||
type string;
|
||||
|
|
@ -52,7 +54,7 @@ cat <<EOF > $fyangA1
|
|||
module A{
|
||||
prefix a;
|
||||
revision 2019-01-01;
|
||||
revision 814-01-28;
|
||||
revision 0814-01-28;
|
||||
namespace "urn:example:a";
|
||||
/* leaf a0 has been removed */
|
||||
leaf a1{
|
||||
|
|
@ -171,7 +173,7 @@ cat <<EOF > $dir/non-compat-valid.xml
|
|||
<module-set-id>42</module-set-id>
|
||||
<module>
|
||||
<name>A</name>
|
||||
<revision>814-01-28</revision>
|
||||
<revision>0814-01-28</revision>
|
||||
<namespace>urn:example:a</namespace>
|
||||
</module>
|
||||
<module>
|
||||
|
|
@ -198,7 +200,7 @@ cat <<EOF > $dir/non-compat-invalid.xml
|
|||
<module-set-id>42</module-set-id>
|
||||
<module>
|
||||
<name>A</name>
|
||||
<revision>814-01-28</revision>
|
||||
<revision>0814-01-28</revision>
|
||||
<namespace>urn:example:a</namespace>
|
||||
</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."
|
||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||
(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."
|
||||
(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."
|
||||
(cd $dir; rm -f tmp_db candidate_db running_db startup_db) # remove databases
|
||||
(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
|
||||
# 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; 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>'
|
||||
|
||||
fi
|
||||
fi # valgrindtest
|
||||
|
||||
if [ $BE -ne 0 ]; then
|
||||
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
|
||||
|
||||
OLDDATE=0814-01-28 # This is alphabeticaly after 2018-12-02
|
||||
NEWDATE=2018-12-02
|
||||
|
||||
cfg=$dir/conf_yang.xml
|
||||
fyang1=$dir/$APPNAME@2018-12-02.yang
|
||||
fyang2=$dir/$APPNAME@2018-01-01.yang
|
||||
fyang2=$dir/$APPNAME@$OLDDATE.yang
|
||||
fyang3=$dir/other.yang
|
||||
|
||||
# 1st variant of the example module
|
||||
cat <<EOF > $fyang1
|
||||
module example{
|
||||
prefix ex;
|
||||
revision 2018-12-02;
|
||||
revision $NEWDATE;
|
||||
revision $OLDDATE;
|
||||
namespace "urn:example:clixon";
|
||||
leaf newex{
|
||||
type string;
|
||||
|
|
@ -31,7 +35,7 @@ EOF
|
|||
cat <<EOF > $fyang2
|
||||
module example{
|
||||
prefix ex;
|
||||
revision 2018-01-01;
|
||||
revision $OLDDATE;
|
||||
namespace "urn:example:clixon";
|
||||
leaf oldex{
|
||||
type string;
|
||||
|
|
@ -43,7 +47,7 @@ EOF
|
|||
cat <<EOF > $fyang3
|
||||
module other{
|
||||
prefix oth;
|
||||
revision 2018-01-01;
|
||||
revision $NEWDATE;
|
||||
namespace "urn:example:clixon2";
|
||||
leaf other{
|
||||
type string;
|
||||
|
|
@ -94,19 +98,17 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
if [ $BE -eq 0 ]; then
|
||||
exit # BE
|
||||
fi
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
#--------------------------------------
|
||||
new "2. Load old module as file"
|
||||
|
|
@ -128,12 +130,14 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
# start new backend
|
||||
start_backend -s init -f $cfg
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
# start new backend
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
|
||||
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>]]>]]>$'
|
||||
|
|
@ -144,15 +148,17 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
#--------------------------------------
|
||||
new "3. Load module with no revision"
|
||||
|
|
@ -170,11 +176,13 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
|
||||
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>]]>]]>$'
|
||||
|
|
@ -185,14 +193,16 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
#--------------------------------------
|
||||
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>$IETFRFC</CLICON_YANG_DIR>
|
||||
<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_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
|
|
@ -211,11 +221,13 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
|
||||
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>]]>]]>$'
|
||||
|
|
@ -226,15 +238,17 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
#--------------------------------------
|
||||
new "5. Load dir"
|
||||
|
|
@ -252,11 +266,13 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
|
||||
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>]]>]]>$'
|
||||
|
|
@ -267,15 +283,18 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
#--------------------------------------
|
||||
new "6. Load dir override with file"
|
||||
|
|
@ -294,12 +313,13 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
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>]]>]]>$'
|
||||
|
||||
|
|
@ -309,16 +329,17 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
|
||||
#--------------------------------------
|
||||
new "7. Load dir override with module + revision"
|
||||
|
|
@ -330,7 +351,7 @@ cat <<EOF > $cfg
|
|||
<CLICON_YANG_DIR>$IETFRFC</CLICON_YANG_DIR>
|
||||
<CLICON_YANG_MAIN_DIR>$dir</CLICON_YANG_MAIN_DIR>
|
||||
<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_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
|
|
@ -338,11 +359,13 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
|
||||
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>]]>]]>$'
|
||||
|
|
@ -353,15 +376,17 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
#--------------------------------------
|
||||
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_MAIN_FILE>$fyang2</CLICON_YANG_MAIN_FILE>
|
||||
<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_BACKEND_PIDFILE>/usr/local/var/$APPNAME/$APPNAME.pidfile</CLICON_BACKEND_PIDFILE>
|
||||
<CLICON_XMLDB_DIR>/usr/local/var/$APPNAME</CLICON_XMLDB_DIR>
|
||||
|
|
@ -381,11 +406,13 @@ cat <<EOF > $cfg
|
|||
</clixon-config>
|
||||
EOF
|
||||
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
if [ $BE -ne 0 ]; then
|
||||
new "start backend -s init -f $cfg"
|
||||
start_backend -s init -f $cfg
|
||||
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
new "waiting"
|
||||
sleep $RCWAIT
|
||||
fi
|
||||
|
||||
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>]]>]]>$'
|
||||
|
|
@ -396,14 +423,18 @@ expecteof "$clixon_netconf -qf $cfg" 0 '<rpc><edit-config><target><candidate/></
|
|||
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>]]>]]>$'
|
||||
|
||||
new "Kill backend"
|
||||
# Check if premature kill
|
||||
pid=`pgrep -u root -f clixon_backend`
|
||||
if [ -z "$pid" ]; then
|
||||
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
|
||||
sudo pkill -u root -f clixon_backend
|
||||
fi
|
||||
# kill backend
|
||||
stop_backend -f $cfg
|
||||
sudo pkill -u root -f clixon_backend
|
||||
|
||||
rm -rf $dir
|
||||
fi
|
||||
|
||||
|
||||
rm -rf $dir
|
||||
|
|
|
|||
|
|
@ -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>]]>]]>$'
|
||||
|
||||
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"
|
||||
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